]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
the git describe option --dirty is too new, so don't use it
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
212
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
214
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673         {"#define USETRIPPY\n", " trippy"},
674 };
675
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
695 };
696
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 };
716
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
719 {
720         /// hash lookup data
721         struct r_glsl_permutation_s *hashnext;
722         unsigned int mode;
723         unsigned int permutation;
724
725         /// indicates if we have tried compiling this permutation already
726         qboolean compiled;
727         /// 0 if compilation failed
728         int program;
729         // texture units assigned to each detected uniform
730         int tex_Texture_First;
731         int tex_Texture_Second;
732         int tex_Texture_GammaRamps;
733         int tex_Texture_Normal;
734         int tex_Texture_Color;
735         int tex_Texture_Gloss;
736         int tex_Texture_Glow;
737         int tex_Texture_SecondaryNormal;
738         int tex_Texture_SecondaryColor;
739         int tex_Texture_SecondaryGloss;
740         int tex_Texture_SecondaryGlow;
741         int tex_Texture_Pants;
742         int tex_Texture_Shirt;
743         int tex_Texture_FogHeightTexture;
744         int tex_Texture_FogMask;
745         int tex_Texture_Lightmap;
746         int tex_Texture_Deluxemap;
747         int tex_Texture_Attenuation;
748         int tex_Texture_Cube;
749         int tex_Texture_Refraction;
750         int tex_Texture_Reflection;
751         int tex_Texture_ShadowMap2D;
752         int tex_Texture_CubeProjection;
753         int tex_Texture_ScreenDepth;
754         int tex_Texture_ScreenNormalMap;
755         int tex_Texture_ScreenDiffuse;
756         int tex_Texture_ScreenSpecular;
757         int tex_Texture_ReflectMask;
758         int tex_Texture_ReflectCube;
759         int tex_Texture_BounceGrid;
760         /// locations of detected uniforms in program object, or -1 if not found
761         int loc_Texture_First;
762         int loc_Texture_Second;
763         int loc_Texture_GammaRamps;
764         int loc_Texture_Normal;
765         int loc_Texture_Color;
766         int loc_Texture_Gloss;
767         int loc_Texture_Glow;
768         int loc_Texture_SecondaryNormal;
769         int loc_Texture_SecondaryColor;
770         int loc_Texture_SecondaryGloss;
771         int loc_Texture_SecondaryGlow;
772         int loc_Texture_Pants;
773         int loc_Texture_Shirt;
774         int loc_Texture_FogHeightTexture;
775         int loc_Texture_FogMask;
776         int loc_Texture_Lightmap;
777         int loc_Texture_Deluxemap;
778         int loc_Texture_Attenuation;
779         int loc_Texture_Cube;
780         int loc_Texture_Refraction;
781         int loc_Texture_Reflection;
782         int loc_Texture_ShadowMap2D;
783         int loc_Texture_CubeProjection;
784         int loc_Texture_ScreenDepth;
785         int loc_Texture_ScreenNormalMap;
786         int loc_Texture_ScreenDiffuse;
787         int loc_Texture_ScreenSpecular;
788         int loc_Texture_ReflectMask;
789         int loc_Texture_ReflectCube;
790         int loc_Texture_BounceGrid;
791         int loc_Alpha;
792         int loc_BloomBlur_Parameters;
793         int loc_ClientTime;
794         int loc_Color_Ambient;
795         int loc_Color_Diffuse;
796         int loc_Color_Specular;
797         int loc_Color_Glow;
798         int loc_Color_Pants;
799         int loc_Color_Shirt;
800         int loc_DeferredColor_Ambient;
801         int loc_DeferredColor_Diffuse;
802         int loc_DeferredColor_Specular;
803         int loc_DeferredMod_Diffuse;
804         int loc_DeferredMod_Specular;
805         int loc_DistortScaleRefractReflect;
806         int loc_EyePosition;
807         int loc_FogColor;
808         int loc_FogHeightFade;
809         int loc_FogPlane;
810         int loc_FogPlaneViewDist;
811         int loc_FogRangeRecip;
812         int loc_LightColor;
813         int loc_LightDir;
814         int loc_LightPosition;
815         int loc_OffsetMapping_ScaleSteps;
816         int loc_PixelSize;
817         int loc_ReflectColor;
818         int loc_ReflectFactor;
819         int loc_ReflectOffset;
820         int loc_RefractColor;
821         int loc_Saturation;
822         int loc_ScreenCenterRefractReflect;
823         int loc_ScreenScaleRefractReflect;
824         int loc_ScreenToDepth;
825         int loc_ShadowMap_Parameters;
826         int loc_ShadowMap_TextureScale;
827         int loc_SpecularPower;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 };
864 #define SHADERSTATICPARMS_COUNT 7
865
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
868
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
896 }
897
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901         else \
902                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 {
905         shaderstaticparms_count = 0;
906
907         // emit all
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
915 }
916
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
923
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 {
926         //unsigned int hashdepth = 0;
927         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928         r_glsl_permutation_t *p;
929         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930         {
931                 if (p->mode == mode && p->permutation == permutation)
932                 {
933                         //if (hashdepth > 10)
934                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935                         return p;
936                 }
937                 //hashdepth++;
938         }
939         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940         p->mode = mode;
941         p->permutation = permutation;
942         p->hashnext = r_glsl_permutationhash[mode][hashindex];
943         r_glsl_permutationhash[mode][hashindex] = p;
944         //if (hashdepth > 10)
945         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946         return p;
947 }
948
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
950 {
951         char *shaderstring;
952         if (!filename || !filename[0])
953                 return NULL;
954         if (!strcmp(filename, "glsl/default.glsl"))
955         {
956                 if (!glslshaderstring)
957                 {
958                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959                         if (glslshaderstring)
960                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
961                         else
962                                 glslshaderstring = (char *)builtinshaderstring;
963                 }
964                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
966                 return shaderstring;
967         }
968         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969         if (shaderstring)
970         {
971                 if (printfromdisknotice)
972                         Con_DPrintf("from disk %s... ", filename);
973                 return shaderstring;
974         }
975         return shaderstring;
976 }
977
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
979 {
980         int i;
981         int sampler;
982         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983         char *vertexstring, *geometrystring, *fragmentstring;
984         char permutationname[256];
985         int vertstrings_count = 0;
986         int geomstrings_count = 0;
987         int fragstrings_count = 0;
988         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991
992         if (p->compiled)
993                 return;
994         p->compiled = true;
995         p->program = 0;
996
997         permutationname[0] = 0;
998         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
999         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001
1002         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003
1004         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005         if(vid.support.gl20shaders130)
1006         {
1007                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1013         }
1014
1015         // the first pretext is which type of shader to compile as
1016         // (later these will all be bound together as a program object)
1017         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020
1021         // the second pretext is the mode (for example a light source)
1022         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026
1027         // now add all the permutation pretexts
1028         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029         {
1030                 if (permutation & (1<<i))
1031                 {
1032                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1036                 }
1037                 else
1038                 {
1039                         // keep line numbers correct
1040                         vertstrings_list[vertstrings_count++] = "\n";
1041                         geomstrings_list[geomstrings_count++] = "\n";
1042                         fragstrings_list[fragstrings_count++] = "\n";
1043                 }
1044         }
1045
1046         // add static parms
1047         R_CompileShader_AddStaticParms(mode, permutation);
1048         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049         vertstrings_count += shaderstaticparms_count;
1050         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051         geomstrings_count += shaderstaticparms_count;
1052         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053         fragstrings_count += shaderstaticparms_count;
1054
1055         // now append the shader text itself
1056         vertstrings_list[vertstrings_count++] = vertexstring;
1057         geomstrings_list[geomstrings_count++] = geometrystring;
1058         fragstrings_list[fragstrings_count++] = fragmentstring;
1059
1060         // if any sources were NULL, clear the respective list
1061         if (!vertexstring)
1062                 vertstrings_count = 0;
1063         if (!geometrystring)
1064                 geomstrings_count = 0;
1065         if (!fragmentstring)
1066                 fragstrings_count = 0;
1067
1068         // compile the shader program
1069         if (vertstrings_count + geomstrings_count + fragstrings_count)
1070                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1071         if (p->program)
1072         {
1073                 CHECKGLERROR
1074                 qglUseProgram(p->program);CHECKGLERROR
1075                 // look up all the uniform variable names we care about, so we don't
1076                 // have to look them up every time we set them
1077
1078                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1079                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1080                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1082                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1083                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1084                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1085                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1090                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1091                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1093                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1097                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1098                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1099                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1109                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1111                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1112                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1113                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1114                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1115                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1116                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1117                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1124                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1125                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1126                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1127                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1129                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1130                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1131                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1132                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1134                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1135                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1136                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1137                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1138                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1139                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1142                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1145                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1146                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1147                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1148                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1149                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1150                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1151                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1152                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1153                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163                 // initialize the samplers to refer to the texture units we use
1164                 p->tex_Texture_First = -1;
1165                 p->tex_Texture_Second = -1;
1166                 p->tex_Texture_GammaRamps = -1;
1167                 p->tex_Texture_Normal = -1;
1168                 p->tex_Texture_Color = -1;
1169                 p->tex_Texture_Gloss = -1;
1170                 p->tex_Texture_Glow = -1;
1171                 p->tex_Texture_SecondaryNormal = -1;
1172                 p->tex_Texture_SecondaryColor = -1;
1173                 p->tex_Texture_SecondaryGloss = -1;
1174                 p->tex_Texture_SecondaryGlow = -1;
1175                 p->tex_Texture_Pants = -1;
1176                 p->tex_Texture_Shirt = -1;
1177                 p->tex_Texture_FogHeightTexture = -1;
1178                 p->tex_Texture_FogMask = -1;
1179                 p->tex_Texture_Lightmap = -1;
1180                 p->tex_Texture_Deluxemap = -1;
1181                 p->tex_Texture_Attenuation = -1;
1182                 p->tex_Texture_Cube = -1;
1183                 p->tex_Texture_Refraction = -1;
1184                 p->tex_Texture_Reflection = -1;
1185                 p->tex_Texture_ShadowMap2D = -1;
1186                 p->tex_Texture_CubeProjection = -1;
1187                 p->tex_Texture_ScreenDepth = -1;
1188                 p->tex_Texture_ScreenNormalMap = -1;
1189                 p->tex_Texture_ScreenDiffuse = -1;
1190                 p->tex_Texture_ScreenSpecular = -1;
1191                 p->tex_Texture_ReflectMask = -1;
1192                 p->tex_Texture_ReflectCube = -1;
1193                 p->tex_Texture_BounceGrid = -1;
1194                 sampler = 0;
1195                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1196                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1197                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1198                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1199                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1200                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1201                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1206                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1207                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1208                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1210                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1211                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1212                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1213                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1214                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1215                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1216                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1217                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1224                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1225                 CHECKGLERROR
1226                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1227         }
1228         else
1229                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1230
1231         // free the strings
1232         if (vertexstring)
1233                 Mem_Free(vertexstring);
1234         if (geometrystring)
1235                 Mem_Free(geometrystring);
1236         if (fragmentstring)
1237                 Mem_Free(fragmentstring);
1238 }
1239
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 {
1242         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243         if (r_glsl_permutation != perm)
1244         {
1245                 r_glsl_permutation = perm;
1246                 if (!r_glsl_permutation->program)
1247                 {
1248                         if (!r_glsl_permutation->compiled)
1249                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1250                         if (!r_glsl_permutation->program)
1251                         {
1252                                 // remove features until we find a valid permutation
1253                                 int i;
1254                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255                                 {
1256                                         // reduce i more quickly whenever it would not remove any bits
1257                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258                                         if (!(permutation & j))
1259                                                 continue;
1260                                         permutation -= j;
1261                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262                                         if (!r_glsl_permutation->compiled)
1263                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1264                                         if (r_glsl_permutation->program)
1265                                                 break;
1266                                 }
1267                                 if (i >= SHADERPERMUTATION_COUNT)
1268                                 {
1269                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         qglUseProgram(0);CHECKGLERROR
1272                                         return; // no bit left to clear, entire mode is broken
1273                                 }
1274                         }
1275                 }
1276                 CHECKGLERROR
1277                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278         }
1279         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1282 }
1283
1284 #ifdef SUPPORTD3D
1285
1286 #ifdef SUPPORTD3D
1287 #include <d3d9.h>
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1290 #endif
1291
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1294 {
1295         /// hash lookup data
1296         struct r_hlsl_permutation_s *hashnext;
1297         unsigned int mode;
1298         unsigned int permutation;
1299
1300         /// indicates if we have tried compiling this permutation already
1301         qboolean compiled;
1302         /// NULL if compilation failed
1303         IDirect3DVertexShader9 *vertexshader;
1304         IDirect3DPixelShader9 *pixelshader;
1305 }
1306 r_hlsl_permutation_t;
1307
1308 typedef enum D3DVSREGISTER_e
1309 {
1310         D3DVSREGISTER_TexMatrix = 0, // float4x4
1311         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315         D3DVSREGISTER_ModelToLight = 20, // float4x4
1316         D3DVSREGISTER_EyePosition = 24,
1317         D3DVSREGISTER_FogPlane = 25,
1318         D3DVSREGISTER_LightDir = 26,
1319         D3DVSREGISTER_LightPosition = 27,
1320 }
1321 D3DVSREGISTER_t;
1322
1323 typedef enum D3DPSREGISTER_e
1324 {
1325         D3DPSREGISTER_Alpha = 0,
1326         D3DPSREGISTER_BloomBlur_Parameters = 1,
1327         D3DPSREGISTER_ClientTime = 2,
1328         D3DPSREGISTER_Color_Ambient = 3,
1329         D3DPSREGISTER_Color_Diffuse = 4,
1330         D3DPSREGISTER_Color_Specular = 5,
1331         D3DPSREGISTER_Color_Glow = 6,
1332         D3DPSREGISTER_Color_Pants = 7,
1333         D3DPSREGISTER_Color_Shirt = 8,
1334         D3DPSREGISTER_DeferredColor_Ambient = 9,
1335         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336         D3DPSREGISTER_DeferredColor_Specular = 11,
1337         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338         D3DPSREGISTER_DeferredMod_Specular = 13,
1339         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340         D3DPSREGISTER_EyePosition = 15, // unused
1341         D3DPSREGISTER_FogColor = 16,
1342         D3DPSREGISTER_FogHeightFade = 17,
1343         D3DPSREGISTER_FogPlane = 18,
1344         D3DPSREGISTER_FogPlaneViewDist = 19,
1345         D3DPSREGISTER_FogRangeRecip = 20,
1346         D3DPSREGISTER_LightColor = 21,
1347         D3DPSREGISTER_LightDir = 22, // unused
1348         D3DPSREGISTER_LightPosition = 23,
1349         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350         D3DPSREGISTER_PixelSize = 25,
1351         D3DPSREGISTER_ReflectColor = 26,
1352         D3DPSREGISTER_ReflectFactor = 27,
1353         D3DPSREGISTER_ReflectOffset = 28,
1354         D3DPSREGISTER_RefractColor = 29,
1355         D3DPSREGISTER_Saturation = 30,
1356         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358         D3DPSREGISTER_ScreenToDepth = 33,
1359         D3DPSREGISTER_ShadowMap_Parameters = 34,
1360         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361         D3DPSREGISTER_SpecularPower = 36,
1362         D3DPSREGISTER_UserVec1 = 37,
1363         D3DPSREGISTER_UserVec2 = 38,
1364         D3DPSREGISTER_UserVec3 = 39,
1365         D3DPSREGISTER_UserVec4 = 40,
1366         D3DPSREGISTER_ViewTintColor = 41,
1367         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368         D3DPSREGISTER_BloomColorSubtract = 43,
1369         D3DPSREGISTER_ViewToLight = 44, // float4x4
1370         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371         D3DPSREGISTER_NormalmapScrollBlend = 52,
1372         // next at 53
1373 }
1374 D3DPSREGISTER_t;
1375
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1382
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 {
1385         //unsigned int hashdepth = 0;
1386         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387         r_hlsl_permutation_t *p;
1388         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389         {
1390                 if (p->mode == mode && p->permutation == permutation)
1391                 {
1392                         //if (hashdepth > 10)
1393                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394                         return p;
1395                 }
1396                 //hashdepth++;
1397         }
1398         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399         p->mode = mode;
1400         p->permutation = permutation;
1401         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402         r_hlsl_permutationhash[mode][hashindex] = p;
1403         //if (hashdepth > 10)
1404         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405         return p;
1406 }
1407
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1409 {
1410         char *shaderstring;
1411         if (!filename || !filename[0])
1412                 return NULL;
1413         if (!strcmp(filename, "hlsl/default.hlsl"))
1414         {
1415                 if (!hlslshaderstring)
1416                 {
1417                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418                         if (hlslshaderstring)
1419                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420                         else
1421                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1422                 }
1423                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425                 return shaderstring;
1426         }
1427         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428         if (shaderstring)
1429         {
1430                 if (printfromdisknotice)
1431                         Con_DPrintf("from disk %s... ", filename);
1432                 return shaderstring;
1433         }
1434         return shaderstring;
1435 }
1436
1437 #include <d3dx9.h>
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1440
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 {
1443         DWORD *vsbin = NULL;
1444         DWORD *psbin = NULL;
1445         fs_offset_t vsbinsize;
1446         fs_offset_t psbinsize;
1447 //      IDirect3DVertexShader9 *vs = NULL;
1448 //      IDirect3DPixelShader9 *ps = NULL;
1449         ID3DXBuffer *vslog = NULL;
1450         ID3DXBuffer *vsbuffer = NULL;
1451         ID3DXConstantTable *vsconstanttable = NULL;
1452         ID3DXBuffer *pslog = NULL;
1453         ID3DXBuffer *psbuffer = NULL;
1454         ID3DXConstantTable *psconstanttable = NULL;
1455         int vsresult = 0;
1456         int psresult = 0;
1457         char temp[MAX_INPUTLINE];
1458         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459         qboolean debugshader = gl_paranoid.integer != 0;
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (!debugshader)
1463         {
1464                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466         }
1467         if ((!vsbin && vertstring) || (!psbin && fragstring))
1468         {
1469                 const char* dllnames_d3dx9 [] =
1470                 {
1471                         "d3dx9_43.dll",
1472                         "d3dx9_42.dll",
1473                         "d3dx9_41.dll",
1474                         "d3dx9_40.dll",
1475                         "d3dx9_39.dll",
1476                         "d3dx9_38.dll",
1477                         "d3dx9_37.dll",
1478                         "d3dx9_36.dll",
1479                         "d3dx9_35.dll",
1480                         "d3dx9_34.dll",
1481                         "d3dx9_33.dll",
1482                         "d3dx9_32.dll",
1483                         "d3dx9_31.dll",
1484                         "d3dx9_30.dll",
1485                         "d3dx9_29.dll",
1486                         "d3dx9_28.dll",
1487                         "d3dx9_27.dll",
1488                         "d3dx9_26.dll",
1489                         "d3dx9_25.dll",
1490                         "d3dx9_24.dll",
1491                         NULL
1492                 };
1493                 dllhandle_t d3dx9_dll = NULL;
1494                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497                 dllfunction_t d3dx9_dllfuncs[] =
1498                 {
1499                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1500                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1501                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1502                         {NULL, NULL}
1503                 };
1504                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505                 {
1506                         DWORD shaderflags = 0;
1507                         if (debugshader)
1508                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511                         if (vertstring && vertstring[0])
1512                         {
1513                                 if (debugshader)
1514                                 {
1515 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 }
1520                                 else
1521                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1522                                 if (vsbuffer)
1523                                 {
1524                                         vsbinsize = vsbuffer->GetBufferSize();
1525                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527                                         vsbuffer->Release();
1528                                 }
1529                                 if (vslog)
1530                                 {
1531                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1533                                         vslog->Release();
1534                                 }
1535                         }
1536                         if (fragstring && fragstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 }
1545                                 else
1546                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1547                                 if (psbuffer)
1548                                 {
1549                                         psbinsize = psbuffer->GetBufferSize();
1550                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552                                         psbuffer->Release();
1553                                 }
1554                                 if (pslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         pslog->Release();
1559                                 }
1560                         }
1561                         Sys_UnloadLibrary(&d3dx9_dll);
1562                 }
1563                 else
1564                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1565         }
1566         if (vsbin && psbin)
1567         {
1568                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569                 if (FAILED(vsresult))
1570                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572                 if (FAILED(psresult))
1573                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574         }
1575         // free the shader data
1576         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1578 }
1579
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1581 {
1582         int i;
1583         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584         int vertstring_length = 0;
1585         int geomstring_length = 0;
1586         int fragstring_length = 0;
1587         char *t;
1588         char *vertexstring, *geometrystring, *fragmentstring;
1589         char *vertstring, *geomstring, *fragstring;
1590         char permutationname[256];
1591         char cachename[256];
1592         int vertstrings_count = 0;
1593         int geomstrings_count = 0;
1594         int fragstrings_count = 0;
1595         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598
1599         if (p->compiled)
1600                 return;
1601         p->compiled = true;
1602         p->vertexshader = NULL;
1603         p->pixelshader = NULL;
1604
1605         permutationname[0] = 0;
1606         cachename[0] = 0;
1607         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610
1611         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612         strlcat(cachename, "hlsl/", sizeof(cachename));
1613
1614         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615         vertstrings_count = 0;
1616         geomstrings_count = 0;
1617         fragstrings_count = 0;
1618         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621
1622         // the first pretext is which type of shader to compile as
1623         // (later these will all be bound together as a program object)
1624         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627
1628         // the second pretext is the mode (for example a light source)
1629         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633         strlcat(cachename, modeinfo->name, sizeof(cachename));
1634
1635         // now add all the permutation pretexts
1636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637         {
1638                 if (permutation & (1<<i))
1639                 {
1640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1645                 }
1646                 else
1647                 {
1648                         // keep line numbers correct
1649                         vertstrings_list[vertstrings_count++] = "\n";
1650                         geomstrings_list[geomstrings_count++] = "\n";
1651                         fragstrings_list[fragstrings_count++] = "\n";
1652                 }
1653         }
1654
1655         // add static parms
1656         R_CompileShader_AddStaticParms(mode, permutation);
1657         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         vertstrings_count += shaderstaticparms_count;
1659         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         geomstrings_count += shaderstaticparms_count;
1661         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662         fragstrings_count += shaderstaticparms_count;
1663
1664         // replace spaces in the cachename with _ characters
1665         for (i = 0;cachename[i];i++)
1666                 if (cachename[i] == ' ')
1667                         cachename[i] = '_';
1668
1669         // now append the shader text itself
1670         vertstrings_list[vertstrings_count++] = vertexstring;
1671         geomstrings_list[geomstrings_count++] = geometrystring;
1672         fragstrings_list[fragstrings_count++] = fragmentstring;
1673
1674         // if any sources were NULL, clear the respective list
1675         if (!vertexstring)
1676                 vertstrings_count = 0;
1677         if (!geometrystring)
1678                 geomstrings_count = 0;
1679         if (!fragmentstring)
1680                 fragstrings_count = 0;
1681
1682         vertstring_length = 0;
1683         for (i = 0;i < vertstrings_count;i++)
1684                 vertstring_length += strlen(vertstrings_list[i]);
1685         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688
1689         geomstring_length = 0;
1690         for (i = 0;i < geomstrings_count;i++)
1691                 geomstring_length += strlen(geomstrings_list[i]);
1692         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695
1696         fragstring_length = 0;
1697         for (i = 0;i < fragstrings_count;i++)
1698                 fragstring_length += strlen(fragstrings_list[i]);
1699         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702
1703         // try to load the cached shader, or generate one
1704         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705
1706         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708         else
1709                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1710
1711         // free the strings
1712         if (vertstring)
1713                 Mem_Free(vertstring);
1714         if (geomstring)
1715                 Mem_Free(geomstring);
1716         if (fragstring)
1717                 Mem_Free(fragstring);
1718         if (vertexstring)
1719                 Mem_Free(vertexstring);
1720         if (geometrystring)
1721                 Mem_Free(geometrystring);
1722         if (fragmentstring)
1723                 Mem_Free(fragmentstring);
1724 }
1725
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1731 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1732
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 {
1742         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743         if (r_hlsl_permutation != perm)
1744         {
1745                 r_hlsl_permutation = perm;
1746                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                 {
1748                         if (!r_hlsl_permutation->compiled)
1749                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1750                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751                         {
1752                                 // remove features until we find a valid permutation
1753                                 int i;
1754                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755                                 {
1756                                         // reduce i more quickly whenever it would not remove any bits
1757                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758                                         if (!(permutation & j))
1759                                                 continue;
1760                                         permutation -= j;
1761                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762                                         if (!r_hlsl_permutation->compiled)
1763                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1764                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1765                                                 break;
1766                                 }
1767                                 if (i >= SHADERPERMUTATION_COUNT)
1768                                 {
1769                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         return; // no bit left to clear, entire mode is broken
1772                                 }
1773                         }
1774                 }
1775                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777         }
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1781 }
1782 #endif
1783
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 {
1786         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1790 }
1791
1792 void R_GLSL_Restart_f(void)
1793 {
1794         unsigned int i, limit;
1795         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796                 Mem_Free(glslshaderstring);
1797         glslshaderstring = NULL;
1798         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799                 Mem_Free(hlslshaderstring);
1800         hlslshaderstring = NULL;
1801         switch(vid.renderpath)
1802         {
1803         case RENDERPATH_D3D9:
1804 #ifdef SUPPORTD3D
1805                 {
1806                         r_hlsl_permutation_t *p;
1807                         r_hlsl_permutation = NULL;
1808                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809                         for (i = 0;i < limit;i++)
1810                         {
1811                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812                                 {
1813                                         if (p->vertexshader)
1814                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1815                                         if (p->pixelshader)
1816                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1817                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1818                                 }
1819                         }
1820                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1821                 }
1822 #endif
1823                 break;
1824         case RENDERPATH_D3D10:
1825                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_D3D11:
1828                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829                 break;
1830         case RENDERPATH_GL20:
1831         case RENDERPATH_GLES2:
1832                 {
1833                         r_glsl_permutation_t *p;
1834                         r_glsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839                                 {
1840                                         GL_Backend_FreeProgram(p->program);
1841                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1845                 }
1846                 break;
1847         case RENDERPATH_GL11:
1848         case RENDERPATH_GL13:
1849         case RENDERPATH_GLES1:
1850                 break;
1851         case RENDERPATH_SOFT:
1852                 break;
1853         }
1854 }
1855
1856 void R_GLSL_DumpShader_f(void)
1857 {
1858         int i;
1859         qfile_t *file;
1860
1861         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862         if (file)
1863         {
1864                 FS_Print(file, "/* The engine may define the following macros:\n");
1865                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866                 for (i = 0;i < SHADERMODE_COUNT;i++)
1867                         FS_Print(file, glslshadermodeinfo[i].pretext);
1868                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869                         FS_Print(file, shaderpermutationinfo[i].pretext);
1870                 FS_Print(file, "*/\n");
1871                 FS_Print(file, builtinshaderstring);
1872                 FS_Close(file);
1873                 Con_Printf("glsl/default.glsl written\n");
1874         }
1875         else
1876                 Con_Printf("failed to write to glsl/default.glsl\n");
1877
1878         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879         if (file)
1880         {
1881                 FS_Print(file, "/* The engine may define the following macros:\n");
1882                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883                 for (i = 0;i < SHADERMODE_COUNT;i++)
1884                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1885                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886                         FS_Print(file, shaderpermutationinfo[i].pretext);
1887                 FS_Print(file, "*/\n");
1888                 FS_Print(file, builtinhlslshaderstring);
1889                 FS_Close(file);
1890                 Con_Printf("hlsl/default.hlsl written\n");
1891         }
1892         else
1893                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 }
1895
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1897 {
1898         unsigned int permutation = 0;
1899         if (r_trippy.integer && !notrippy)
1900                 permutation |= SHADERPERMUTATION_TRIPPY;
1901         permutation |= SHADERPERMUTATION_VIEWTINT;
1902         if (first)
1903                 permutation |= SHADERPERMUTATION_DIFFUSE;
1904         if (second)
1905                 permutation |= SHADERPERMUTATION_SPECULAR;
1906         if (texturemode == GL_MODULATE)
1907                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908         else if (texturemode == GL_ADD)
1909                 permutation |= SHADERPERMUTATION_GLOW;
1910         else if (texturemode == GL_DECAL)
1911                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1912         if (!second)
1913                 texturemode = GL_MODULATE;
1914         switch (vid.renderpath)
1915         {
1916         case RENDERPATH_D3D9:
1917 #ifdef SUPPORTD3D
1918                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1919                 R_Mesh_TexBind(GL20TU_FIRST , first );
1920                 R_Mesh_TexBind(GL20TU_SECOND, second);
1921 #endif
1922                 break;
1923         case RENDERPATH_D3D10:
1924                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925                 break;
1926         case RENDERPATH_D3D11:
1927                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_GL20:
1930         case RENDERPATH_GLES2:
1931                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1932                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1933                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1934                 break;
1935         case RENDERPATH_GL13:
1936         case RENDERPATH_GLES1:
1937                 R_Mesh_TexBind(0, first );
1938                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1939                 R_Mesh_TexBind(1, second);
1940                 if (second)
1941                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1942                 break;
1943         case RENDERPATH_GL11:
1944                 R_Mesh_TexBind(0, first );
1945                 break;
1946         case RENDERPATH_SOFT:
1947                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 break;
1951         }
1952 }
1953
1954 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1955 {
1956         unsigned int permutation = 0;
1957         if (r_trippy.integer && !notrippy)
1958                 permutation |= SHADERPERMUTATION_TRIPPY;
1959         switch (vid.renderpath)
1960         {
1961         case RENDERPATH_D3D9:
1962 #ifdef SUPPORTD3D
1963                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1964 #endif
1965                 break;
1966         case RENDERPATH_D3D10:
1967                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1968                 break;
1969         case RENDERPATH_D3D11:
1970                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1971                 break;
1972         case RENDERPATH_GL20:
1973         case RENDERPATH_GLES2:
1974                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1975                 break;
1976         case RENDERPATH_GL13:
1977         case RENDERPATH_GLES1:
1978                 R_Mesh_TexBind(0, 0);
1979                 R_Mesh_TexBind(1, 0);
1980                 break;
1981         case RENDERPATH_GL11:
1982                 R_Mesh_TexBind(0, 0);
1983                 break;
1984         case RENDERPATH_SOFT:
1985                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1986                 break;
1987         }
1988 }
1989
1990 void R_SetupShader_ShowDepth(qboolean notrippy)
1991 {
1992         int permutation = 0;
1993         if (r_trippy.integer && !notrippy)
1994                 permutation |= SHADERPERMUTATION_TRIPPY;
1995         if (r_trippy.integer)
1996                 permutation |= SHADERPERMUTATION_TRIPPY;
1997         switch (vid.renderpath)
1998         {
1999         case RENDERPATH_D3D9:
2000 #ifdef SUPPORTHLSL
2001                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2002 #endif
2003                 break;
2004         case RENDERPATH_D3D10:
2005                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2006                 break;
2007         case RENDERPATH_D3D11:
2008                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_GL20:
2011         case RENDERPATH_GLES2:
2012                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2013                 break;
2014         case RENDERPATH_GL13:
2015         case RENDERPATH_GLES1:
2016                 break;
2017         case RENDERPATH_GL11:
2018                 break;
2019         case RENDERPATH_SOFT:
2020                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2021                 break;
2022         }
2023 }
2024
2025 extern qboolean r_shadow_usingdeferredprepass;
2026 extern cvar_t r_shadow_deferred_8bitrange;
2027 extern rtexture_t *r_shadow_attenuationgradienttexture;
2028 extern rtexture_t *r_shadow_attenuation2dtexture;
2029 extern rtexture_t *r_shadow_attenuation3dtexture;
2030 extern qboolean r_shadow_usingshadowmap2d;
2031 extern qboolean r_shadow_usingshadowmaportho;
2032 extern float r_shadow_shadowmap_texturescale[2];
2033 extern float r_shadow_shadowmap_parameters[4];
2034 extern qboolean r_shadow_shadowmapvsdct;
2035 extern qboolean r_shadow_shadowmapsampler;
2036 extern int r_shadow_shadowmappcf;
2037 extern rtexture_t *r_shadow_shadowmap2dtexture;
2038 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2039 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2040 extern matrix4x4_t r_shadow_shadowmapmatrix;
2041 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2042 extern int r_shadow_prepass_width;
2043 extern int r_shadow_prepass_height;
2044 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2045 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2046 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2047 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2048 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2049
2050 #define BLENDFUNC_ALLOWS_COLORMOD      1
2051 #define BLENDFUNC_ALLOWS_FOG           2
2052 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2053 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2054 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2055 static int R_BlendFuncFlags(int src, int dst)
2056 {
2057         int r = 0;
2058
2059         // a blendfunc allows colormod if:
2060         // a) it can never keep the destination pixel invariant, or
2061         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2062         // this is to prevent unintended side effects from colormod
2063
2064         // a blendfunc allows fog if:
2065         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2066         // this is to prevent unintended side effects from fog
2067
2068         // these checks are the output of fogeval.pl
2069
2070         r |= BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2074         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2080         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092
2093         return r;
2094 }
2095
2096 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2097 {
2098         // select a permutation of the lighting shader appropriate to this
2099         // combination of texture, entity, light source, and fogging, only use the
2100         // minimum features necessary to avoid wasting rendering time in the
2101         // fragment shader on features that are not being used
2102         unsigned int permutation = 0;
2103         unsigned int mode = 0;
2104         int blendfuncflags;
2105         static float dummy_colormod[3] = {1, 1, 1};
2106         float *colormod = rsurface.colormod;
2107         float m16f[16];
2108         matrix4x4_t tempmatrix;
2109         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2110         if (r_trippy.integer && !notrippy)
2111                 permutation |= SHADERPERMUTATION_TRIPPY;
2112         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2113                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2114         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2115                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2116         if (rsurfacepass == RSURFPASS_BACKGROUND)
2117         {
2118                 // distorted background
2119                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2120                 {
2121                         mode = SHADERMODE_WATER;
2122                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2123                         {
2124                                 // this is the right thing to do for wateralpha
2125                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2126                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2127                         }
2128                         else
2129                         {
2130                                 // this is the right thing to do for entity alpha
2131                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2132                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2133                         }
2134                 }
2135                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2136                 {
2137                         mode = SHADERMODE_REFRACTION;
2138                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2140                 }
2141                 else
2142                 {
2143                         mode = SHADERMODE_GENERIC;
2144                         permutation |= SHADERPERMUTATION_DIFFUSE;
2145                         GL_BlendFunc(GL_ONE, GL_ZERO);
2146                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2147                 }
2148         }
2149         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2150         {
2151                 if (r_glsl_offsetmapping.integer)
2152                 {
2153                         switch(rsurface.texture->offsetmapping)
2154                         {
2155                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158                         case OFFSETMAPPING_OFF: break;
2159                         }
2160                 }
2161                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2163                 // normalmap (deferred prepass), may use alpha test on diffuse
2164                 mode = SHADERMODE_DEFERREDGEOMETRY;
2165                 GL_BlendFunc(GL_ONE, GL_ZERO);
2166                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167         }
2168         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2169         {
2170                 if (r_glsl_offsetmapping.integer)
2171                 {
2172                         switch(rsurface.texture->offsetmapping)
2173                         {
2174                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2175                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2176                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2177                         case OFFSETMAPPING_OFF: break;
2178                         }
2179                 }
2180                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2181                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2182                 // light source
2183                 mode = SHADERMODE_LIGHTSOURCE;
2184                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2185                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2186                 if (diffusescale > 0)
2187                         permutation |= SHADERPERMUTATION_DIFFUSE;
2188                 if (specularscale > 0)
2189                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2190                 if (r_refdef.fogenabled)
2191                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2192                 if (rsurface.texture->colormapping)
2193                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2194                 if (r_shadow_usingshadowmap2d)
2195                 {
2196                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2197                         if(r_shadow_shadowmapvsdct)
2198                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2199
2200                         if (r_shadow_shadowmapsampler)
2201                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2202                         if (r_shadow_shadowmappcf > 1)
2203                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2204                         else if (r_shadow_shadowmappcf)
2205                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2206                 }
2207                 if (rsurface.texture->reflectmasktexture)
2208                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2209                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2210                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2211         }
2212         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2213         {
2214                 if (r_glsl_offsetmapping.integer)
2215                 {
2216                         switch(rsurface.texture->offsetmapping)
2217                         {
2218                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_OFF: break;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // unshaded geometry (fullbright or ambient model lighting)
2227                 mode = SHADERMODE_FLATCOLOR;
2228                 ambientscale = diffusescale = specularscale = 0;
2229                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2230                         permutation |= SHADERPERMUTATION_GLOW;
2231                 if (r_refdef.fogenabled)
2232                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2233                 if (rsurface.texture->colormapping)
2234                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2235                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2236                 {
2237                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2238                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2239
2240                         if (r_shadow_shadowmapsampler)
2241                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242                         if (r_shadow_shadowmappcf > 1)
2243                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244                         else if (r_shadow_shadowmappcf)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2246                 }
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2248                         permutation |= SHADERPERMUTATION_REFLECTION;
2249                 if (rsurface.texture->reflectmasktexture)
2250                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2251                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2252                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2253         }
2254         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2255         {
2256                 if (r_glsl_offsetmapping.integer)
2257                 {
2258                         switch(rsurface.texture->offsetmapping)
2259                         {
2260                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2261                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2263                         case OFFSETMAPPING_OFF: break;
2264                         }
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2267                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2268                 // directional model lighting
2269                 mode = SHADERMODE_LIGHTDIRECTION;
2270                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2271                         permutation |= SHADERPERMUTATION_GLOW;
2272                 permutation |= SHADERPERMUTATION_DIFFUSE;
2273                 if (specularscale > 0)
2274                         permutation |= SHADERPERMUTATION_SPECULAR;
2275                 if (r_refdef.fogenabled)
2276                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2277                 if (rsurface.texture->colormapping)
2278                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2279                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2280                 {
2281                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2282                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2283
2284                         if (r_shadow_shadowmapsampler)
2285                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2286                         if (r_shadow_shadowmappcf > 1)
2287                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2288                         else if (r_shadow_shadowmappcf)
2289                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2290                 }
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2292                         permutation |= SHADERPERMUTATION_REFLECTION;
2293                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2294                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2295                 if (rsurface.texture->reflectmasktexture)
2296                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2297                 if (r_shadow_bouncegridtexture)
2298                 {
2299                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2300                         if (r_shadow_bouncegriddirectional)
2301                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2302                 }
2303                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305         }
2306         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2307         {
2308                 if (r_glsl_offsetmapping.integer)
2309                 {
2310                         switch(rsurface.texture->offsetmapping)
2311                         {
2312                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2313                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_OFF: break;
2316                         }
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320                 // ambient model lighting
2321                 mode = SHADERMODE_LIGHTDIRECTION;
2322                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2323                         permutation |= SHADERPERMUTATION_GLOW;
2324                 if (r_refdef.fogenabled)
2325                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2326                 if (rsurface.texture->colormapping)
2327                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2328                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2329                 {
2330                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2331                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2332
2333                         if (r_shadow_shadowmapsampler)
2334                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2335                         if (r_shadow_shadowmappcf > 1)
2336                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2337                         else if (r_shadow_shadowmappcf)
2338                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341                         permutation |= SHADERPERMUTATION_REFLECTION;
2342                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2343                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2344                 if (rsurface.texture->reflectmasktexture)
2345                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2346                 if (r_shadow_bouncegridtexture)
2347                 {
2348                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2349                         if (r_shadow_bouncegriddirectional)
2350                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2351                 }
2352                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354         }
2355         else
2356         {
2357                 if (r_glsl_offsetmapping.integer)
2358                 {
2359                         switch(rsurface.texture->offsetmapping)
2360                         {
2361                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364                         case OFFSETMAPPING_OFF: break;
2365                         }
2366                 }
2367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369                 // lightmapped wall
2370                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371                         permutation |= SHADERPERMUTATION_GLOW;
2372                 if (r_refdef.fogenabled)
2373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374                 if (rsurface.texture->colormapping)
2375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377                 {
2378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380
2381                         if (r_shadow_shadowmapsampler)
2382                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2383                         if (r_shadow_shadowmappcf > 1)
2384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2385                         else if (r_shadow_shadowmappcf)
2386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2389                         permutation |= SHADERPERMUTATION_REFLECTION;
2390                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2391                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2392                 if (rsurface.texture->reflectmasktexture)
2393                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2394                 if (FAKELIGHT_ENABLED)
2395                 {
2396                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2397                         mode = SHADERMODE_FAKELIGHT;
2398                         permutation |= SHADERPERMUTATION_DIFFUSE;
2399                         if (specularscale > 0)
2400                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401                 }
2402                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2403                 {
2404                         // deluxemapping (light direction texture)
2405                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2406                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2407                         else
2408                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2409                         permutation |= SHADERPERMUTATION_DIFFUSE;
2410                         if (specularscale > 0)
2411                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2412                 }
2413                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2414                 {
2415                         // fake deluxemapping (uniform light direction in tangentspace)
2416                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2417                         permutation |= SHADERPERMUTATION_DIFFUSE;
2418                         if (specularscale > 0)
2419                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2420                 }
2421                 else if (rsurface.uselightmaptexture)
2422                 {
2423                         // ordinary lightmapping (q1bsp, q3bsp)
2424                         mode = SHADERMODE_LIGHTMAP;
2425                 }
2426                 else
2427                 {
2428                         // ordinary vertex coloring (q3bsp)
2429                         mode = SHADERMODE_VERTEXCOLOR;
2430                 }
2431                 if (r_shadow_bouncegridtexture)
2432                 {
2433                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2434                         if (r_shadow_bouncegriddirectional)
2435                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2436                 }
2437                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2439         }
2440         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2441                 colormod = dummy_colormod;
2442         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2443                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2444         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2445                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2446         switch(vid.renderpath)
2447         {
2448         case RENDERPATH_D3D9:
2449 #ifdef SUPPORTD3D
2450                 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);
2451                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2452                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2453                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2454                 if (mode == SHADERMODE_LIGHTSOURCE)
2455                 {
2456                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2457                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458                 }
2459                 else
2460                 {
2461                         if (mode == SHADERMODE_LIGHTDIRECTION)
2462                         {
2463                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2464                         }
2465                 }
2466                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2467                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2468                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2469                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2470                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2471
2472                 if (mode == SHADERMODE_LIGHTSOURCE)
2473                 {
2474                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2475                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2476                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2477                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2478                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2479
2480                         // additive passes are only darkened by fog, not tinted
2481                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2482                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2483                 }
2484                 else
2485                 {
2486                         if (mode == SHADERMODE_FLATCOLOR)
2487                         {
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2489                         }
2490                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2491                         {
2492                                 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]);
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2494                                 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);
2495                                 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);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2498                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2499                         }
2500                         else
2501                         {
2502                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2504                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2506                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2507                         }
2508                         // additive passes are only darkened by fog, not tinted
2509                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2510                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2511                         else
2512                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2513                         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);
2514                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2515                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2516                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2518                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2519                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2520                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2521                         if (mode == SHADERMODE_WATER)
2522                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2523                 }
2524                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2525                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2526                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2527                 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));
2528                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529                 if (rsurface.texture->pantstexture)
2530                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2531                 else
2532                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2533                 if (rsurface.texture->shirttexture)
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2535                 else
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2537                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2539                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2540                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2541                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2542                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2543                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2544                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2545                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2546                         );
2547                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2548                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2549
2550                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2551                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2552                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2553                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2554                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2555                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2556                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2557                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2558                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2559                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2560                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2561                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2562                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2563                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2564                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2565                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2566                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2567                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2568                 {
2569                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2570                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2571                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2572                 }
2573                 else
2574                 {
2575                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2576                 }
2577 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2578 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2579                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2580                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2581                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2582                 {
2583                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2584                         if (rsurface.rtlight)
2585                         {
2586                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2587                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2588                         }
2589                 }
2590 #endif
2591                 break;
2592         case RENDERPATH_D3D10:
2593                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2594                 break;
2595         case RENDERPATH_D3D11:
2596                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2597                 break;
2598         case RENDERPATH_GL20:
2599         case RENDERPATH_GLES2:
2600                 if (!vid.useinterleavedarrays)
2601                 {
2602                         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);
2603                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2604                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2605                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2606                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2607                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2608                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2609                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2610                 }
2611                 else
2612                 {
2613                         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);
2614                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2615                 }
2616                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2617                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2618                 if (mode == SHADERMODE_LIGHTSOURCE)
2619                 {
2620                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2621                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2622                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2623                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2624                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2625                         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);
2626         
2627                         // additive passes are only darkened by fog, not tinted
2628                         if (r_glsl_permutation->loc_FogColor >= 0)
2629                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2630                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2631                 }
2632                 else
2633                 {
2634                         if (mode == SHADERMODE_FLATCOLOR)
2635                         {
2636                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2637                         }
2638                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2639                         {
2640                                 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]);
2641                                 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]);
2642                                 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);
2643                                 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);
2644                                 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);
2645                                 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]);
2646                                 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]);
2647                         }
2648                         else
2649                         {
2650                                 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]);
2651                                 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]);
2652                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2653                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2654                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2655                         }
2656                         // additive passes are only darkened by fog, not tinted
2657                         if (r_glsl_permutation->loc_FogColor >= 0)
2658                         {
2659                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2660                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2661                                 else
2662                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2663                         }
2664                         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);
2665                         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]);
2666                         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]);
2667                         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]);
2668                         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]);
2669                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2670                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2671                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2672                         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]);
2673                 }
2674                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2675                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2676                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2677                 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]);
2678                 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]);
2679
2680                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2681                 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));
2682                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2683                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2684                 {
2685                         if (rsurface.texture->pantstexture)
2686                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2687                         else
2688                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2689                 }
2690                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2691                 {
2692                         if (rsurface.texture->shirttexture)
2693                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2694                         else
2695                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2696                 }
2697                 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]);
2698                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2699                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2700                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2701                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2702                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2703                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2704                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2705                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2706                         );
2707                 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]);
2708                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2709                 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);}
2710                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2711
2712                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2713                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2714                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2715                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2716                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2717                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2718                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2719                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2720                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2721                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2722                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2723                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2724                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2725                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2726                 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);
2727                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2728                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2729                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2730                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2731                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2732                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2733                 {
2734                         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);
2735                         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);
2736                         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);
2737                 }
2738                 else
2739                 {
2740                         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);
2741                 }
2742                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2743                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2744                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2745                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2746                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2747                 {
2748                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2749                         if (rsurface.rtlight)
2750                         {
2751                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2752                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2753                         }
2754                 }
2755                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2756                 CHECKGLERROR
2757                 break;
2758         case RENDERPATH_GL11:
2759         case RENDERPATH_GL13:
2760         case RENDERPATH_GLES1:
2761                 break;
2762         case RENDERPATH_SOFT:
2763                 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);
2764                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2765                 R_SetupShader_SetPermutationSoft(mode, permutation);
2766                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2767                 if (mode == SHADERMODE_LIGHTSOURCE)
2768                 {
2769                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2770                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2771                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2772                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2773                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2774                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2775         
2776                         // additive passes are only darkened by fog, not tinted
2777                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2778                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2779                 }
2780                 else
2781                 {
2782                         if (mode == SHADERMODE_FLATCOLOR)
2783                         {
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2785                         }
2786                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2787                         {
2788                                 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]);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2790                                 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);
2791                                 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);
2792                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2793                                 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]);
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2795                         }
2796                         else
2797                         {
2798                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2799                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2800                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2801                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2802                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2803                         }
2804                         // additive passes are only darkened by fog, not tinted
2805                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2806                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2807                         else
2808                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2809                         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);
2810                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2811                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2812                         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]);
2813                         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]);
2814                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2815                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2816                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2817                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2818                 }
2819                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2820                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2821                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2822                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2823                 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]);
2824
2825                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2826                 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));
2827                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2828                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2829                 {
2830                         if (rsurface.texture->pantstexture)
2831                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2832                         else
2833                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2834                 }
2835                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2836                 {
2837                         if (rsurface.texture->shirttexture)
2838                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2839                         else
2840                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2841                 }
2842                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2843                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2844                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2845                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2846                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2847                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2848                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2850                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2851                         );
2852                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2853                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2854
2855                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2856                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2857                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2858                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2859                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2860                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2861                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2862                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2863                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2864                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2865                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2866                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2867                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2868                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2869                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2870                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2871                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2872                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2873                 {
2874                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2875                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2876                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2877                 }
2878                 else
2879                 {
2880                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2881                 }
2882 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2883 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2884                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2885                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2886                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2887                 {
2888                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2889                         if (rsurface.rtlight)
2890                         {
2891                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2892                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2893                         }
2894                 }
2895                 break;
2896         }
2897 }
2898
2899 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2900 {
2901         // select a permutation of the lighting shader appropriate to this
2902         // combination of texture, entity, light source, and fogging, only use the
2903         // minimum features necessary to avoid wasting rendering time in the
2904         // fragment shader on features that are not being used
2905         unsigned int permutation = 0;
2906         unsigned int mode = 0;
2907         const float *lightcolorbase = rtlight->currentcolor;
2908         float ambientscale = rtlight->ambientscale;
2909         float diffusescale = rtlight->diffusescale;
2910         float specularscale = rtlight->specularscale;
2911         // this is the location of the light in view space
2912         vec3_t viewlightorigin;
2913         // this transforms from view space (camera) to light space (cubemap)
2914         matrix4x4_t viewtolight;
2915         matrix4x4_t lighttoview;
2916         float viewtolight16f[16];
2917         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2918         // light source
2919         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2920         if (rtlight->currentcubemap != r_texture_whitecube)
2921                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2922         if (diffusescale > 0)
2923                 permutation |= SHADERPERMUTATION_DIFFUSE;
2924         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2925                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2926         if (r_shadow_usingshadowmap2d)
2927         {
2928                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2929                 if (r_shadow_shadowmapvsdct)
2930                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2931
2932                 if (r_shadow_shadowmapsampler)
2933                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2934                 if (r_shadow_shadowmappcf > 1)
2935                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2936                 else if (r_shadow_shadowmappcf)
2937                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2938         }
2939         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2940         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2941         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2942         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2943         switch(vid.renderpath)
2944         {
2945         case RENDERPATH_D3D9:
2946 #ifdef SUPPORTD3D
2947                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2948                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2949                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2950                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2951                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2952                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2953                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2954                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2955                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2956                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2957                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2958
2959                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2960                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2961                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2962                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2963                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2964                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2965 #endif
2966                 break;
2967         case RENDERPATH_D3D10:
2968                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2969                 break;
2970         case RENDERPATH_D3D11:
2971                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2972                 break;
2973         case RENDERPATH_GL20:
2974         case RENDERPATH_GLES2:
2975                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2978                 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);
2979                 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);
2980                 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);
2981                 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]);
2982                 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]);
2983                 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));
2984                 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]);
2985                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2986
2987                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2988                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2989                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2990                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2991                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2992                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2993                 break;
2994         case RENDERPATH_GL11:
2995         case RENDERPATH_GL13:
2996         case RENDERPATH_GLES1:
2997                 break;
2998         case RENDERPATH_SOFT:
2999                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3000                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3001                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3002                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3003                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3004                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3005                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3006                 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]);
3007                 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));
3008                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3009                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3010
3011                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3012                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3013                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3014                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3015                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3016                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3017                 break;
3018         }
3019 }
3020
3021 #define SKINFRAME_HASH 1024
3022
3023 typedef struct
3024 {
3025         int loadsequence; // incremented each level change
3026         memexpandablearray_t array;
3027         skinframe_t *hash[SKINFRAME_HASH];
3028 }
3029 r_skinframe_t;
3030 r_skinframe_t r_skinframe;
3031
3032 void R_SkinFrame_PrepareForPurge(void)
3033 {
3034         r_skinframe.loadsequence++;
3035         // wrap it without hitting zero
3036         if (r_skinframe.loadsequence >= 200)
3037                 r_skinframe.loadsequence = 1;
3038 }
3039
3040 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3041 {
3042         if (!skinframe)
3043                 return;
3044         // mark the skinframe as used for the purging code
3045         skinframe->loadsequence = r_skinframe.loadsequence;
3046 }
3047
3048 void R_SkinFrame_Purge(void)
3049 {
3050         int i;
3051         skinframe_t *s;
3052         for (i = 0;i < SKINFRAME_HASH;i++)
3053         {
3054                 for (s = r_skinframe.hash[i];s;s = s->next)
3055                 {
3056                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3057                         {
3058                                 if (s->merged == s->base)
3059                                         s->merged = NULL;
3060                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3061                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3062                                 R_PurgeTexture(s->merged);s->merged = NULL;
3063                                 R_PurgeTexture(s->base  );s->base   = NULL;
3064                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3065                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3066                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3067                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3068                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3069                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3070                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3071                                 s->loadsequence = 0;
3072                         }
3073                 }
3074         }
3075 }
3076
3077 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3078         skinframe_t *item;
3079         char basename[MAX_QPATH];
3080
3081         Image_StripImageExtension(name, basename, sizeof(basename));
3082
3083         if( last == NULL ) {
3084                 int hashindex;
3085                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3086                 item = r_skinframe.hash[hashindex];
3087         } else {
3088                 item = last->next;
3089         }
3090
3091         // linearly search through the hash bucket
3092         for( ; item ; item = item->next ) {
3093                 if( !strcmp( item->basename, basename ) ) {
3094                         return item;
3095                 }
3096         }
3097         return NULL;
3098 }
3099
3100 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3101 {
3102         skinframe_t *item;
3103         int hashindex;
3104         char basename[MAX_QPATH];
3105
3106         Image_StripImageExtension(name, basename, sizeof(basename));
3107
3108         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3109         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3110                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3111                         break;
3112
3113         if (!item) {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 dyntexture = CL_GetDynTexture( basename );
3117                 if (!add && !dyntexture)
3118                         return NULL;
3119                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3120                 memset(item, 0, sizeof(*item));
3121                 strlcpy(item->basename, basename, sizeof(item->basename));
3122                 item->base = dyntexture; // either NULL or dyntexture handle
3123                 item->textureflags = textureflags;
3124                 item->comparewidth = comparewidth;
3125                 item->compareheight = compareheight;
3126                 item->comparecrc = comparecrc;
3127                 item->next = r_skinframe.hash[hashindex];
3128                 r_skinframe.hash[hashindex] = item;
3129         }
3130         else if( item->base == NULL )
3131         {
3132                 rtexture_t *dyntexture;
3133                 // check whether its a dynamic texture
3134                 // 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]
3135                 dyntexture = CL_GetDynTexture( basename );
3136                 item->base = dyntexture; // either NULL or dyntexture handle
3137         }
3138
3139         R_SkinFrame_MarkUsed(item);
3140         return item;
3141 }
3142
3143 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3144         { \
3145                 unsigned long long avgcolor[5], wsum; \
3146                 int pix, comp, w; \
3147                 avgcolor[0] = 0; \
3148                 avgcolor[1] = 0; \
3149                 avgcolor[2] = 0; \
3150                 avgcolor[3] = 0; \
3151                 avgcolor[4] = 0; \
3152                 wsum = 0; \
3153                 for(pix = 0; pix < cnt; ++pix) \
3154                 { \
3155                         w = 0; \
3156                         for(comp = 0; comp < 3; ++comp) \
3157                                 w += getpixel; \
3158                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3159                         { \
3160                                 ++wsum; \
3161                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3162                                 w = getpixel; \
3163                                 for(comp = 0; comp < 3; ++comp) \
3164                                         avgcolor[comp] += getpixel * w; \
3165                                 avgcolor[3] += w; \
3166                         } \
3167                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3168                         avgcolor[4] += getpixel; \
3169                 } \
3170                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3171                         avgcolor[3] = 1; \
3172                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3173                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3174                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3175                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3176         }
3177
3178 extern cvar_t gl_picmip;
3179 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3180 {
3181         int j;
3182         unsigned char *pixels;
3183         unsigned char *bumppixels;
3184         unsigned char *basepixels = NULL;
3185         int basepixels_width = 0;
3186         int basepixels_height = 0;
3187         skinframe_t *skinframe;
3188         rtexture_t *ddsbase = NULL;
3189         qboolean ddshasalpha = false;
3190         float ddsavgcolor[4];
3191         char basename[MAX_QPATH];
3192         int miplevel = R_PicmipForFlags(textureflags);
3193         int savemiplevel = miplevel;
3194         int mymiplevel;
3195
3196         if (cls.state == ca_dedicated)
3197                 return NULL;
3198
3199         // return an existing skinframe if already loaded
3200         // if loading of the first image fails, don't make a new skinframe as it
3201         // would cause all future lookups of this to be missing
3202         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3203         if (skinframe && skinframe->base)
3204                 return skinframe;
3205
3206         Image_StripImageExtension(name, basename, sizeof(basename));
3207
3208         // check for DDS texture file first
3209         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3210         {
3211                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3212                 if (basepixels == NULL)
3213                         return NULL;
3214         }
3215
3216         // FIXME handle miplevel
3217
3218         if (developer_loading.integer)
3219                 Con_Printf("loading skin \"%s\"\n", name);
3220
3221         // we've got some pixels to store, so really allocate this new texture now
3222         if (!skinframe)
3223                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3224         skinframe->stain = NULL;
3225         skinframe->merged = NULL;
3226         skinframe->base = NULL;
3227         skinframe->pants = NULL;
3228         skinframe->shirt = NULL;
3229         skinframe->nmap = NULL;
3230         skinframe->gloss = NULL;
3231         skinframe->glow = NULL;
3232         skinframe->fog = NULL;
3233         skinframe->reflect = NULL;
3234         skinframe->hasalpha = false;
3235
3236         if (ddsbase)
3237         {
3238                 skinframe->base = ddsbase;
3239                 skinframe->hasalpha = ddshasalpha;
3240                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3241                 if (r_loadfog && skinframe->hasalpha)
3242                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3243                 //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]);
3244         }
3245         else
3246         {
3247                 basepixels_width = image_width;
3248                 basepixels_height = image_height;
3249                 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);
3250                 if (textureflags & TEXF_ALPHA)
3251                 {
3252                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3253                         {
3254                                 if (basepixels[j] < 255)
3255                                 {
3256                                         skinframe->hasalpha = true;
3257                                         break;
3258                                 }
3259                         }
3260                         if (r_loadfog && skinframe->hasalpha)
3261                         {
3262                                 // has transparent pixels
3263                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3264                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3265                                 {
3266                                         pixels[j+0] = 255;
3267                                         pixels[j+1] = 255;
3268                                         pixels[j+2] = 255;
3269                                         pixels[j+3] = basepixels[j+3];
3270                                 }
3271                                 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);
3272                                 Mem_Free(pixels);
3273                         }
3274                 }
3275                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3276                 //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]);
3277                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3278                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3279                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3280                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3281         }
3282
3283         if (r_loaddds)
3284         {
3285                 mymiplevel = savemiplevel;
3286                 if (r_loadnormalmap)
3287                         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);
3288                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3289                 if (r_loadgloss)
3290                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3291                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3292                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3293                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3294         }
3295
3296         // _norm is the name used by tenebrae and has been adopted as standard
3297         if (r_loadnormalmap && skinframe->nmap == NULL)
3298         {
3299                 mymiplevel = savemiplevel;
3300                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3301                 {
3302                         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);
3303                         Mem_Free(pixels);
3304                         pixels = NULL;
3305                 }
3306                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3307                 {
3308                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3309                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3310                         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);
3311                         Mem_Free(pixels);
3312                         Mem_Free(bumppixels);
3313                 }
3314                 else if (r_shadow_bumpscale_basetexture.value > 0)
3315                 {
3316                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3317                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3318                         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);
3319                         Mem_Free(pixels);
3320                 }
3321                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3322                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3323         }
3324
3325         // _luma is supported only for tenebrae compatibility
3326         // _glow is the preferred name
3327         mymiplevel = savemiplevel;
3328         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))))
3329         {
3330                 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);
3331                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3332                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3333                 Mem_Free(pixels);pixels = NULL;
3334         }
3335
3336         mymiplevel = savemiplevel;
3337         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3338         {
3339                 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);
3340                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3341                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3342                 Mem_Free(pixels);
3343                 pixels = NULL;
3344         }
3345
3346         mymiplevel = savemiplevel;
3347         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3348         {
3349                 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);
3350                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3351                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3352                 Mem_Free(pixels);
3353                 pixels = NULL;
3354         }
3355
3356         mymiplevel = savemiplevel;
3357         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3358         {
3359                 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);
3360                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3361                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3362                 Mem_Free(pixels);
3363                 pixels = NULL;
3364         }
3365
3366         mymiplevel = savemiplevel;
3367         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3368         {
3369                 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);
3370                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3371                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3372                 Mem_Free(pixels);
3373                 pixels = NULL;
3374         }
3375
3376         if (basepixels)
3377                 Mem_Free(basepixels);
3378
3379         return skinframe;
3380 }
3381
3382 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3383 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3384 {
3385         int i;
3386         unsigned char *temp1, *temp2;
3387         skinframe_t *skinframe;
3388
3389         if (cls.state == ca_dedicated)
3390                 return NULL;
3391
3392         // if already loaded just return it, otherwise make a new skinframe
3393         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3394         if (skinframe && skinframe->base)
3395                 return skinframe;
3396
3397         skinframe->stain = NULL;
3398         skinframe->merged = NULL;
3399         skinframe->base = NULL;
3400         skinframe->pants = NULL;
3401         skinframe->shirt = NULL;
3402         skinframe->nmap = NULL;
3403         skinframe->gloss = NULL;
3404         skinframe->glow = NULL;
3405         skinframe->fog = NULL;
3406         skinframe->reflect = NULL;
3407         skinframe->hasalpha = false;
3408
3409         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3410         if (!skindata)
3411                 return NULL;
3412
3413         if (developer_loading.integer)
3414                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3415
3416         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3417         {
3418                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3419                 temp2 = temp1 + width * height * 4;
3420                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3421                 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);
3422                 Mem_Free(temp1);
3423         }
3424         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3425         if (textureflags & TEXF_ALPHA)
3426         {
3427                 for (i = 3;i < width * height * 4;i += 4)
3428                 {
3429                         if (skindata[i] < 255)
3430                         {
3431                                 skinframe->hasalpha = true;
3432                                 break;
3433                         }
3434                 }
3435                 if (r_loadfog && skinframe->hasalpha)
3436                 {
3437                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3438                         memcpy(fogpixels, skindata, width * height * 4);
3439                         for (i = 0;i < width * height * 4;i += 4)
3440                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3441                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3442                         Mem_Free(fogpixels);
3443                 }
3444         }
3445
3446         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3447         //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]);
3448
3449         return skinframe;
3450 }
3451
3452 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3453 {
3454         int i;
3455         int featuresmask;
3456         skinframe_t *skinframe;
3457
3458         if (cls.state == ca_dedicated)
3459                 return NULL;
3460
3461         // if already loaded just return it, otherwise make a new skinframe
3462         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3463         if (skinframe && skinframe->base)
3464                 return skinframe;
3465
3466         skinframe->stain = NULL;
3467         skinframe->merged = NULL;
3468         skinframe->base = NULL;
3469         skinframe->pants = NULL;
3470         skinframe->shirt = NULL;
3471         skinframe->nmap = NULL;
3472         skinframe->gloss = NULL;
3473         skinframe->glow = NULL;
3474         skinframe->fog = NULL;
3475         skinframe->reflect = NULL;
3476         skinframe->hasalpha = false;
3477
3478         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3479         if (!skindata)
3480                 return NULL;
3481
3482         if (developer_loading.integer)
3483                 Con_Printf("loading quake skin \"%s\"\n", name);
3484
3485         // 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)
3486         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3487         memcpy(skinframe->qpixels, skindata, width*height);
3488         skinframe->qwidth = width;
3489         skinframe->qheight = height;
3490
3491         featuresmask = 0;
3492         for (i = 0;i < width * height;i++)
3493                 featuresmask |= palette_featureflags[skindata[i]];
3494
3495         skinframe->hasalpha = false;
3496         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3497         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3498         skinframe->qgeneratemerged = true;
3499         skinframe->qgeneratebase = skinframe->qhascolormapping;
3500         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3501
3502         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3503         //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]);
3504
3505         return skinframe;
3506 }
3507
3508 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3509 {
3510         int width;
3511         int height;
3512         unsigned char *skindata;
3513
3514         if (!skinframe->qpixels)
3515                 return;
3516
3517         if (!skinframe->qhascolormapping)
3518                 colormapped = false;
3519
3520         if (colormapped)
3521         {
3522                 if (!skinframe->qgeneratebase)
3523                         return;
3524         }
3525         else
3526         {
3527                 if (!skinframe->qgeneratemerged)
3528                         return;
3529         }
3530
3531         width = skinframe->qwidth;
3532         height = skinframe->qheight;
3533         skindata = skinframe->qpixels;
3534
3535         if (skinframe->qgeneratenmap)
3536         {
3537                 unsigned char *temp1, *temp2;
3538                 skinframe->qgeneratenmap = false;
3539                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3540                 temp2 = temp1 + width * height * 4;
3541                 // use either a custom palette or the quake palette
3542                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3543                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3544                 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);
3545                 Mem_Free(temp1);
3546         }
3547
3548         if (skinframe->qgenerateglow)
3549         {
3550                 skinframe->qgenerateglow = false;
3551                 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
3552         }
3553
3554         if (colormapped)
3555         {
3556                 skinframe->qgeneratebase = false;
3557                 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);
3558                 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);
3559                 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);
3560         }
3561         else
3562         {
3563                 skinframe->qgeneratemerged = false;
3564                 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);
3565         }
3566
3567         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3568         {
3569                 Mem_Free(skinframe->qpixels);
3570                 skinframe->qpixels = NULL;
3571         }
3572 }
3573
3574 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)
3575 {
3576         int i;
3577         skinframe_t *skinframe;
3578
3579         if (cls.state == ca_dedicated)
3580                 return NULL;
3581
3582         // if already loaded just return it, otherwise make a new skinframe
3583         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3584         if (skinframe && skinframe->base)
3585                 return skinframe;
3586
3587         skinframe->stain = NULL;
3588         skinframe->merged = NULL;
3589         skinframe->base = NULL;
3590         skinframe->pants = NULL;
3591         skinframe->shirt = NULL;
3592         skinframe->nmap = NULL;
3593         skinframe->gloss = NULL;
3594         skinframe->glow = NULL;
3595         skinframe->fog = NULL;
3596         skinframe->reflect = NULL;
3597         skinframe->hasalpha = false;
3598
3599         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3600         if (!skindata)
3601                 return NULL;
3602
3603         if (developer_loading.integer)
3604                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3605
3606         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3607         if (textureflags & TEXF_ALPHA)
3608         {
3609                 for (i = 0;i < width * height;i++)
3610                 {
3611                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3612                         {
3613                                 skinframe->hasalpha = true;
3614                                 break;
3615                         }
3616                 }
3617                 if (r_loadfog && skinframe->hasalpha)
3618                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3619         }
3620
3621         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3622         //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]);
3623
3624         return skinframe;
3625 }
3626
3627 skinframe_t *R_SkinFrame_LoadMissing(void)
3628 {
3629         skinframe_t *skinframe;
3630
3631         if (cls.state == ca_dedicated)
3632                 return NULL;
3633
3634         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3635         skinframe->stain = NULL;
3636         skinframe->merged = NULL;
3637         skinframe->base = NULL;
3638         skinframe->pants = NULL;
3639         skinframe->shirt = NULL;
3640         skinframe->nmap = NULL;
3641         skinframe->gloss = NULL;
3642         skinframe->glow = NULL;
3643         skinframe->fog = NULL;
3644         skinframe->reflect = NULL;
3645         skinframe->hasalpha = false;
3646
3647         skinframe->avgcolor[0] = rand() / RAND_MAX;
3648         skinframe->avgcolor[1] = rand() / RAND_MAX;
3649         skinframe->avgcolor[2] = rand() / RAND_MAX;
3650         skinframe->avgcolor[3] = 1;
3651
3652         return skinframe;
3653 }
3654
3655 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3656 typedef struct suffixinfo_s
3657 {
3658         const char *suffix;
3659         qboolean flipx, flipy, flipdiagonal;
3660 }
3661 suffixinfo_t;
3662 static suffixinfo_t suffix[3][6] =
3663 {
3664         {
3665                 {"px",   false, false, false},
3666                 {"nx",   false, false, false},
3667                 {"py",   false, false, false},
3668                 {"ny",   false, false, false},
3669                 {"pz",   false, false, false},
3670                 {"nz",   false, false, false}
3671         },
3672         {
3673                 {"posx", false, false, false},
3674                 {"negx", false, false, false},
3675                 {"posy", false, false, false},
3676                 {"negy", false, false, false},
3677                 {"posz", false, false, false},
3678                 {"negz", false, false, false}
3679         },
3680         {
3681                 {"rt",    true, false,  true},
3682                 {"lf",   false,  true,  true},
3683                 {"ft",    true,  true, false},
3684                 {"bk",   false, false, false},
3685                 {"up",    true, false,  true},
3686                 {"dn",    true, false,  true}
3687         }
3688 };
3689
3690 static int componentorder[4] = {0, 1, 2, 3};
3691
3692 rtexture_t *R_LoadCubemap(const char *basename)
3693 {
3694         int i, j, cubemapsize;
3695         unsigned char *cubemappixels, *image_buffer;
3696         rtexture_t *cubemaptexture;
3697         char name[256];
3698         // must start 0 so the first loadimagepixels has no requested width/height
3699         cubemapsize = 0;
3700         cubemappixels = NULL;
3701         cubemaptexture = NULL;
3702         // keep trying different suffix groups (posx, px, rt) until one loads
3703         for (j = 0;j < 3 && !cubemappixels;j++)
3704         {
3705                 // load the 6 images in the suffix group
3706                 for (i = 0;i < 6;i++)
3707                 {
3708                         // generate an image name based on the base and and suffix
3709                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3710                         // load it
3711                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3712                         {
3713                                 // an image loaded, make sure width and height are equal
3714                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3715                                 {
3716                                         // if this is the first image to load successfully, allocate the cubemap memory
3717                                         if (!cubemappixels && image_width >= 1)
3718                                         {
3719                                                 cubemapsize = image_width;
3720                                                 // note this clears to black, so unavailable sides are black
3721                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3722                                         }
3723                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3724                                         if (cubemappixels)
3725                                                 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);
3726                                 }
3727                                 else
3728                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3729                                 // free the image
3730                                 Mem_Free(image_buffer);
3731                         }
3732                 }
3733         }
3734         // if a cubemap loaded, upload it
3735         if (cubemappixels)
3736         {
3737                 if (developer_loading.integer)
3738                         Con_Printf("loading cubemap \"%s\"\n", basename);
3739
3740                 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);
3741                 Mem_Free(cubemappixels);
3742         }
3743         else
3744         {
3745                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3746                 if (developer_loading.integer)
3747                 {
3748                         Con_Printf("(tried tried images ");
3749                         for (j = 0;j < 3;j++)
3750                                 for (i = 0;i < 6;i++)
3751                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3752                         Con_Print(" and was unable to find any of them).\n");
3753                 }
3754         }
3755         return cubemaptexture;
3756 }
3757
3758 rtexture_t *R_GetCubemap(const char *basename)
3759 {
3760         int i;
3761         for (i = 0;i < r_texture_numcubemaps;i++)
3762                 if (r_texture_cubemaps[i] != NULL)
3763                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3764                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3765         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3766                 return r_texture_whitecube;
3767         r_texture_numcubemaps++;
3768         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3769         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3770         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3771         return r_texture_cubemaps[i]->texture;
3772 }
3773
3774 void R_FreeCubemap(const char *basename)
3775 {
3776         int i;
3777
3778         for (i = 0;i < r_texture_numcubemaps;i++)
3779         {
3780                 if (r_texture_cubemaps[i] != NULL)
3781                 {
3782                         if (r_texture_cubemaps[i]->texture)
3783                         {
3784                                 if (developer_loading.integer)
3785                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3786                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3787                                 Mem_Free(r_texture_cubemaps[i]);
3788                                 r_texture_cubemaps[i] = NULL;
3789                         }
3790                 }
3791         }
3792 }
3793
3794 void R_FreeCubemaps(void)
3795 {
3796         int i;
3797         for (i = 0;i < r_texture_numcubemaps;i++)
3798         {
3799                 if (developer_loading.integer)
3800                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3801                 if (r_texture_cubemaps[i] != NULL)
3802                 {
3803                         if (r_texture_cubemaps[i]->texture)
3804                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3805                         Mem_Free(r_texture_cubemaps[i]);
3806                 }
3807         }
3808         r_texture_numcubemaps = 0;
3809 }
3810
3811 void R_Main_FreeViewCache(void)
3812 {
3813         if (r_refdef.viewcache.entityvisible)
3814                 Mem_Free(r_refdef.viewcache.entityvisible);
3815         if (r_refdef.viewcache.world_pvsbits)
3816                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3817         if (r_refdef.viewcache.world_leafvisible)
3818                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3819         if (r_refdef.viewcache.world_surfacevisible)
3820                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3822 }
3823
3824 void R_Main_ResizeViewCache(void)
3825 {
3826         int numentities = r_refdef.scene.numentities;
3827         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3828         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3829         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3830         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3831         if (r_refdef.viewcache.maxentities < numentities)
3832         {
3833                 r_refdef.viewcache.maxentities = numentities;
3834                 if (r_refdef.viewcache.entityvisible)
3835                         Mem_Free(r_refdef.viewcache.entityvisible);
3836                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3837         }
3838         if (r_refdef.viewcache.world_numclusters != numclusters)
3839         {
3840                 r_refdef.viewcache.world_numclusters = numclusters;
3841                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3842                 if (r_refdef.viewcache.world_pvsbits)
3843                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3844                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3845         }
3846         if (r_refdef.viewcache.world_numleafs != numleafs)
3847         {
3848                 r_refdef.viewcache.world_numleafs = numleafs;
3849                 if (r_refdef.viewcache.world_leafvisible)
3850                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3851                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3852         }
3853         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3854         {
3855                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3856                 if (r_refdef.viewcache.world_surfacevisible)
3857                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3858                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3859         }
3860 }
3861
3862 extern rtexture_t *loadingscreentexture;
3863 void gl_main_start(void)
3864 {
3865         loadingscreentexture = NULL;
3866         r_texture_blanknormalmap = NULL;
3867         r_texture_white = NULL;
3868         r_texture_grey128 = NULL;
3869         r_texture_black = NULL;
3870         r_texture_whitecube = NULL;
3871         r_texture_normalizationcube = NULL;
3872         r_texture_fogattenuation = NULL;
3873         r_texture_fogheighttexture = NULL;
3874         r_texture_gammaramps = NULL;
3875         r_texture_numcubemaps = 0;
3876
3877         r_loaddds = r_texture_dds_load.integer != 0;
3878         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3879
3880         switch(vid.renderpath)
3881         {
3882         case RENDERPATH_GL20:
3883         case RENDERPATH_D3D9:
3884         case RENDERPATH_D3D10:
3885         case RENDERPATH_D3D11:
3886         case RENDERPATH_SOFT:
3887         case RENDERPATH_GLES2:
3888                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3889                 Cvar_SetValueQuick(&gl_combine, 1);
3890                 Cvar_SetValueQuick(&r_glsl, 1);
3891                 r_loadnormalmap = true;
3892                 r_loadgloss = true;
3893                 r_loadfog = false;
3894                 break;
3895         case RENDERPATH_GL13:
3896         case RENDERPATH_GLES1:
3897                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3898                 Cvar_SetValueQuick(&gl_combine, 1);
3899                 Cvar_SetValueQuick(&r_glsl, 0);
3900                 r_loadnormalmap = false;
3901                 r_loadgloss = false;
3902                 r_loadfog = true;
3903                 break;
3904         case RENDERPATH_GL11:
3905                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3906                 Cvar_SetValueQuick(&gl_combine, 0);
3907                 Cvar_SetValueQuick(&r_glsl, 0);
3908                 r_loadnormalmap = false;
3909                 r_loadgloss = false;
3910                 r_loadfog = true;
3911                 break;
3912         }
3913
3914         R_AnimCache_Free();
3915         R_FrameData_Reset();
3916
3917         r_numqueries = 0;
3918         r_maxqueries = 0;
3919         memset(r_queries, 0, sizeof(r_queries));
3920
3921         r_qwskincache = NULL;
3922         r_qwskincache_size = 0;
3923
3924         // due to caching of texture_t references, the collision cache must be reset
3925         Collision_Cache_Reset(true);
3926
3927         // set up r_skinframe loading system for textures
3928         memset(&r_skinframe, 0, sizeof(r_skinframe));
3929         r_skinframe.loadsequence = 1;
3930         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3931
3932         r_main_texturepool = R_AllocTexturePool();
3933         R_BuildBlankTextures();
3934         R_BuildNoTexture();
3935         if (vid.support.arb_texture_cube_map)
3936         {
3937                 R_BuildWhiteCube();
3938                 R_BuildNormalizationCube();
3939         }
3940         r_texture_fogattenuation = NULL;
3941         r_texture_fogheighttexture = NULL;
3942         r_texture_gammaramps = NULL;
3943         //r_texture_fogintensity = NULL;
3944         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3945         memset(&r_waterstate, 0, sizeof(r_waterstate));
3946         r_glsl_permutation = NULL;
3947         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3948         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3949         glslshaderstring = NULL;
3950 #ifdef SUPPORTD3D
3951         r_hlsl_permutation = NULL;
3952         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3953         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3954 #endif
3955         hlslshaderstring = NULL;
3956         memset(&r_svbsp, 0, sizeof (r_svbsp));
3957
3958         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3959         r_texture_numcubemaps = 0;
3960
3961         r_refdef.fogmasktable_density = 0;
3962 }
3963
3964 void gl_main_shutdown(void)
3965 {
3966         R_AnimCache_Free();
3967         R_FrameData_Reset();
3968
3969         R_Main_FreeViewCache();
3970
3971         switch(vid.renderpath)
3972         {
3973         case RENDERPATH_GL11:
3974         case RENDERPATH_GL13:
3975         case RENDERPATH_GL20:
3976         case RENDERPATH_GLES1:
3977         case RENDERPATH_GLES2:
3978                 if (r_maxqueries)
3979                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3980                 break;
3981         case RENDERPATH_D3D9:
3982                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3983                 break;
3984         case RENDERPATH_D3D10:
3985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3986                 break;
3987         case RENDERPATH_D3D11:
3988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3989                 break;
3990         case RENDERPATH_SOFT:
3991                 break;
3992         }
3993
3994         r_numqueries = 0;
3995         r_maxqueries = 0;
3996         memset(r_queries, 0, sizeof(r_queries));
3997
3998         r_qwskincache = NULL;
3999         r_qwskincache_size = 0;
4000
4001         // clear out the r_skinframe state
4002         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4003         memset(&r_skinframe, 0, sizeof(r_skinframe));
4004
4005         if (r_svbsp.nodes)
4006                 Mem_Free(r_svbsp.nodes);
4007         memset(&r_svbsp, 0, sizeof (r_svbsp));
4008         R_FreeTexturePool(&r_main_texturepool);
4009         loadingscreentexture = NULL;
4010         r_texture_blanknormalmap = NULL;
4011         r_texture_white = NULL;
4012         r_texture_grey128 = NULL;
4013         r_texture_black = NULL;
4014         r_texture_whitecube = NULL;
4015         r_texture_normalizationcube = NULL;
4016         r_texture_fogattenuation = NULL;
4017         r_texture_fogheighttexture = NULL;
4018         r_texture_gammaramps = NULL;
4019         r_texture_numcubemaps = 0;
4020         //r_texture_fogintensity = NULL;
4021         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4022         memset(&r_waterstate, 0, sizeof(r_waterstate));
4023         R_GLSL_Restart_f();
4024
4025         r_glsl_permutation = NULL;
4026         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4027         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4028         glslshaderstring = NULL;
4029 #ifdef SUPPORTD3D
4030         r_hlsl_permutation = NULL;
4031         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4032         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4033 #endif
4034         hlslshaderstring = NULL;
4035 }
4036
4037 extern void CL_ParseEntityLump(char *entitystring);
4038 void gl_main_newmap(void)
4039 {
4040         // FIXME: move this code to client
4041         char *entities, entname[MAX_QPATH];
4042         if (r_qwskincache)
4043                 Mem_Free(r_qwskincache);
4044         r_qwskincache = NULL;
4045         r_qwskincache_size = 0;
4046         if (cl.worldmodel)
4047         {
4048                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4049                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4050                 {
4051                         CL_ParseEntityLump(entities);
4052                         Mem_Free(entities);
4053                         return;
4054                 }
4055                 if (cl.worldmodel->brush.entities)
4056                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4057         }
4058         R_Main_FreeViewCache();
4059
4060         R_FrameData_Reset();
4061 }
4062
4063 void GL_Main_Init(void)
4064 {
4065         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4066
4067         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4068         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4069         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4070         if (gamemode == GAME_NEHAHRA)
4071         {
4072                 Cvar_RegisterVariable (&gl_fogenable);
4073                 Cvar_RegisterVariable (&gl_fogdensity);
4074                 Cvar_RegisterVariable (&gl_fogred);
4075                 Cvar_RegisterVariable (&gl_foggreen);
4076                 Cvar_RegisterVariable (&gl_fogblue);
4077                 Cvar_RegisterVariable (&gl_fogstart);
4078                 Cvar_RegisterVariable (&gl_fogend);
4079                 Cvar_RegisterVariable (&gl_skyclip);
4080         }
4081         Cvar_RegisterVariable(&r_motionblur);
4082         Cvar_RegisterVariable(&r_motionblur_maxblur);
4083         Cvar_RegisterVariable(&r_motionblur_bmin);
4084         Cvar_RegisterVariable(&r_motionblur_vmin);
4085         Cvar_RegisterVariable(&r_motionblur_vmax);
4086         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4087         Cvar_RegisterVariable(&r_motionblur_randomize);
4088         Cvar_RegisterVariable(&r_damageblur);
4089         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4090         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4091         Cvar_RegisterVariable(&r_equalize_entities_by);
4092         Cvar_RegisterVariable(&r_equalize_entities_to);
4093         Cvar_RegisterVariable(&r_depthfirst);
4094         Cvar_RegisterVariable(&r_useinfinitefarclip);
4095         Cvar_RegisterVariable(&r_farclip_base);
4096         Cvar_RegisterVariable(&r_farclip_world);
4097         Cvar_RegisterVariable(&r_nearclip);
4098         Cvar_RegisterVariable(&r_deformvertexes);
4099         Cvar_RegisterVariable(&r_transparent);
4100         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4101         Cvar_RegisterVariable(&r_showoverdraw);
4102         Cvar_RegisterVariable(&r_showbboxes);
4103         Cvar_RegisterVariable(&r_showsurfaces);
4104         Cvar_RegisterVariable(&r_showtris);
4105         Cvar_RegisterVariable(&r_shownormals);
4106         Cvar_RegisterVariable(&r_showlighting);
4107         Cvar_RegisterVariable(&r_showshadowvolumes);
4108         Cvar_RegisterVariable(&r_showcollisionbrushes);
4109         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4110         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4111         Cvar_RegisterVariable(&r_showdisabledepthtest);
4112         Cvar_RegisterVariable(&r_drawportals);
4113         Cvar_RegisterVariable(&r_drawentities);
4114         Cvar_RegisterVariable(&r_draw2d);
4115         Cvar_RegisterVariable(&r_drawworld);
4116         Cvar_RegisterVariable(&r_cullentities_trace);
4117         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4118         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4119         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4120         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4121         Cvar_RegisterVariable(&r_drawviewmodel);
4122         Cvar_RegisterVariable(&r_drawexteriormodel);
4123         Cvar_RegisterVariable(&r_speeds);
4124         Cvar_RegisterVariable(&r_fullbrights);
4125         Cvar_RegisterVariable(&r_wateralpha);
4126         Cvar_RegisterVariable(&r_dynamic);
4127         Cvar_RegisterVariable(&r_fakelight);
4128         Cvar_RegisterVariable(&r_fakelight_intensity);
4129         Cvar_RegisterVariable(&r_fullbright);
4130         Cvar_RegisterVariable(&r_shadows);
4131         Cvar_RegisterVariable(&r_shadows_darken);
4132         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4133         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4134         Cvar_RegisterVariable(&r_shadows_throwdistance);
4135         Cvar_RegisterVariable(&r_shadows_throwdirection);
4136         Cvar_RegisterVariable(&r_shadows_focus);
4137         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4138         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4139         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4140         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4141         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4142         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4143         Cvar_RegisterVariable(&r_fog_exp2);
4144         Cvar_RegisterVariable(&r_fog_clear);
4145         Cvar_RegisterVariable(&r_drawfog);
4146         Cvar_RegisterVariable(&r_transparentdepthmasking);
4147         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4148         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4149         Cvar_RegisterVariable(&r_texture_dds_load);
4150         Cvar_RegisterVariable(&r_texture_dds_save);
4151         Cvar_RegisterVariable(&r_textureunits);
4152         Cvar_RegisterVariable(&gl_combine);
4153         Cvar_RegisterVariable(&r_viewfbo);
4154         Cvar_RegisterVariable(&r_viewscale);
4155         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4156         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4157         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4158         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4159         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4160         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4161         Cvar_RegisterVariable(&r_glsl);
4162         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4163         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4164         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4165         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4166         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4167         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4168         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4169         Cvar_RegisterVariable(&r_glsl_postprocess);
4170         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4171         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4172         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4173         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4174         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4175         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4176         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4177         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4178
4179         Cvar_RegisterVariable(&r_water);
4180         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4181         Cvar_RegisterVariable(&r_water_clippingplanebias);
4182         Cvar_RegisterVariable(&r_water_refractdistort);
4183         Cvar_RegisterVariable(&r_water_reflectdistort);
4184         Cvar_RegisterVariable(&r_water_scissormode);
4185         Cvar_RegisterVariable(&r_water_lowquality);
4186
4187         Cvar_RegisterVariable(&r_lerpsprites);
4188         Cvar_RegisterVariable(&r_lerpmodels);
4189         Cvar_RegisterVariable(&r_lerplightstyles);
4190         Cvar_RegisterVariable(&r_waterscroll);
4191         Cvar_RegisterVariable(&r_bloom);
4192         Cvar_RegisterVariable(&r_bloom_colorscale);
4193         Cvar_RegisterVariable(&r_bloom_brighten);
4194         Cvar_RegisterVariable(&r_bloom_blur);
4195         Cvar_RegisterVariable(&r_bloom_resolution);
4196         Cvar_RegisterVariable(&r_bloom_colorexponent);
4197         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4198         Cvar_RegisterVariable(&r_hdr);
4199         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4200         Cvar_RegisterVariable(&r_hdr_glowintensity);
4201         Cvar_RegisterVariable(&r_hdr_range);
4202         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4203         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4204         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4205         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4206         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4207         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4208         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4209         Cvar_RegisterVariable(&developer_texturelogging);
4210         Cvar_RegisterVariable(&gl_lightmaps);
4211         Cvar_RegisterVariable(&r_test);
4212         Cvar_RegisterVariable(&r_glsl_saturation);
4213         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4214         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4215         Cvar_RegisterVariable(&r_framedatasize);
4216         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4217                 Cvar_SetValue("r_fullbrights", 0);
4218         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4219 }
4220
4221 extern void R_Textures_Init(void);
4222 extern void GL_Draw_Init(void);
4223 extern void GL_Main_Init(void);
4224 extern void R_Shadow_Init(void);
4225 extern void R_Sky_Init(void);
4226 extern void GL_Surf_Init(void);
4227 extern void R_Particles_Init(void);
4228 extern void R_Explosion_Init(void);
4229 extern void gl_backend_init(void);
4230 extern void Sbar_Init(void);
4231 extern void R_LightningBeams_Init(void);
4232 extern void Mod_RenderInit(void);
4233 extern void Font_Init(void);
4234
4235 void Render_Init(void)
4236 {
4237         gl_backend_init();
4238         R_Textures_Init();
4239         GL_Main_Init();
4240         Font_Init();
4241         GL_Draw_Init();
4242         R_Shadow_Init();
4243         R_Sky_Init();
4244         GL_Surf_Init();
4245         Sbar_Init();
4246         R_Particles_Init();
4247         R_Explosion_Init();
4248         R_LightningBeams_Init();
4249         Mod_RenderInit();
4250 }
4251
4252 /*
4253 ===============
4254 GL_Init
4255 ===============
4256 */
4257 extern char *ENGINE_EXTENSIONS;
4258 void GL_Init (void)
4259 {
4260         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4261         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4262         gl_version = (const char *)qglGetString(GL_VERSION);
4263         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4264
4265         if (!gl_extensions)
4266                 gl_extensions = "";
4267         if (!gl_platformextensions)
4268                 gl_platformextensions = "";
4269
4270         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4271         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4272         Con_Printf("GL_VERSION: %s\n", gl_version);
4273         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4274         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4275
4276         VID_CheckExtensions();
4277
4278         // LordHavoc: report supported extensions
4279         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4280
4281         // clear to black (loading plaque will be seen over this)
4282         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4283 }
4284
4285 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4286 {
4287         int i;
4288         mplane_t *p;
4289         if (r_trippy.integer)
4290                 return false;
4291         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4292         {
4293                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4294                 if (i == 4)
4295                         continue;
4296                 p = r_refdef.view.frustum + i;
4297                 switch(p->signbits)
4298                 {
4299                 default:
4300                 case 0:
4301                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 case 1:
4305                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4306                                 return true;
4307                         break;
4308                 case 2:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 3:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 4:
4317                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 5:
4321                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 6:
4325                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 7:
4329                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 }
4333         }
4334         return false;
4335 }
4336
4337 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4338 {
4339         int i;
4340         const mplane_t *p;
4341         if (r_trippy.integer)
4342                 return false;
4343         for (i = 0;i < numplanes;i++)
4344         {
4345                 p = planes + i;
4346                 switch(p->signbits)
4347                 {
4348                 default:
4349                 case 0:
4350                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4351                                 return true;
4352                         break;
4353                 case 1:
4354                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4355                                 return true;
4356                         break;
4357                 case 2:
4358                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4359                                 return true;
4360                         break;
4361                 case 3:
4362                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4363                                 return true;
4364                         break;
4365                 case 4:
4366                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4367                                 return true;
4368                         break;
4369                 case 5:
4370                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4371                                 return true;
4372                         break;
4373                 case 6:
4374                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4375                                 return true;
4376                         break;
4377                 case 7:
4378                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4379                                 return true;
4380                         break;
4381                 }
4382         }
4383         return false;
4384 }
4385
4386 //==================================================================================
4387
4388 // LordHavoc: this stores temporary data used within the same frame
4389
4390 typedef struct r_framedata_mem_s
4391 {
4392         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4393         size_t size; // how much usable space
4394         size_t current; // how much space in use
4395         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4396         size_t wantedsize; // how much space was allocated
4397         unsigned char *data; // start of real data (16byte aligned)
4398 }
4399 r_framedata_mem_t;
4400
4401 static r_framedata_mem_t *r_framedata_mem;
4402
4403 void R_FrameData_Reset(void)
4404 {
4405         while (r_framedata_mem)
4406         {
4407                 r_framedata_mem_t *next = r_framedata_mem->purge;
4408                 Mem_Free(r_framedata_mem);
4409                 r_framedata_mem = next;
4410         }
4411 }
4412
4413 void R_FrameData_Resize(void)
4414 {
4415         size_t wantedsize;
4416         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4417         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4418         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4419         {
4420                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4421                 newmem->wantedsize = wantedsize;
4422                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4423                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4424                 newmem->current = 0;
4425                 newmem->mark = 0;
4426                 newmem->purge = r_framedata_mem;
4427                 r_framedata_mem = newmem;
4428         }
4429 }
4430
4431 void R_FrameData_NewFrame(void)
4432 {
4433         R_FrameData_Resize();
4434         if (!r_framedata_mem)
4435                 return;
4436         // if we ran out of space on the last frame, free the old memory now
4437         while (r_framedata_mem->purge)
4438         {
4439                 // repeatedly remove the second item in the list, leaving only head
4440                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4441                 Mem_Free(r_framedata_mem->purge);
4442                 r_framedata_mem->purge = next;
4443         }
4444         // reset the current mem pointer
4445         r_framedata_mem->current = 0;
4446         r_framedata_mem->mark = 0;
4447 }
4448
4449 void *R_FrameData_Alloc(size_t size)
4450 {
4451         void *data;
4452
4453         // align to 16 byte boundary - the data pointer is already aligned, so we
4454         // only need to ensure the size of every allocation is also aligned
4455         size = (size + 15) & ~15;
4456
4457         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4458         {
4459                 // emergency - we ran out of space, allocate more memory
4460                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4461                 R_FrameData_Resize();
4462         }
4463
4464         data = r_framedata_mem->data + r_framedata_mem->current;
4465         r_framedata_mem->current += size;
4466
4467         // count the usage for stats
4468         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4469         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4470
4471         return (void *)data;
4472 }
4473
4474 void *R_FrameData_Store(size_t size, void *data)
4475 {
4476         void *d = R_FrameData_Alloc(size);
4477         if (d && data)
4478                 memcpy(d, data, size);
4479         return d;
4480 }
4481
4482 void R_FrameData_SetMark(void)
4483 {
4484         if (!r_framedata_mem)
4485                 return;
4486         r_framedata_mem->mark = r_framedata_mem->current;
4487 }
4488
4489 void R_FrameData_ReturnToMark(void)
4490 {
4491         if (!r_framedata_mem)
4492                 return;
4493         r_framedata_mem->current = r_framedata_mem->mark;
4494 }
4495
4496 //==================================================================================
4497
4498 // LordHavoc: animcache originally written by Echon, rewritten since then
4499
4500 /**
4501  * Animation cache prevents re-generating mesh data for an animated model
4502  * multiple times in one frame for lighting, shadowing, reflections, etc.
4503  */
4504
4505 void R_AnimCache_Free(void)
4506 {
4507 }
4508
4509 void R_AnimCache_ClearCache(void)
4510 {
4511         int i;
4512         entity_render_t *ent;
4513
4514         for (i = 0;i < r_refdef.scene.numentities;i++)
4515         {
4516                 ent = r_refdef.scene.entities[i];
4517                 ent->animcache_vertex3f = NULL;
4518                 ent->animcache_normal3f = NULL;
4519                 ent->animcache_svector3f = NULL;
4520                 ent->animcache_tvector3f = NULL;
4521                 ent->animcache_vertexmesh = NULL;
4522                 ent->animcache_vertex3fbuffer = NULL;
4523                 ent->animcache_vertexmeshbuffer = NULL;
4524         }
4525 }
4526
4527 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4528 {
4529         int i;
4530
4531         // check if we need the meshbuffers
4532         if (!vid.useinterleavedarrays)
4533                 return;
4534
4535         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4536                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4537         // TODO: upload vertex3f buffer?
4538         if (ent->animcache_vertexmesh)
4539         {
4540                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4541                 for (i = 0;i < numvertices;i++)
4542                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4543                 if (ent->animcache_svector3f)
4544                         for (i = 0;i < numvertices;i++)
4545                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4546                 if (ent->animcache_tvector3f)
4547                         for (i = 0;i < numvertices;i++)
4548                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4549                 if (ent->animcache_normal3f)
4550                         for (i = 0;i < numvertices;i++)
4551                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4552                 // TODO: upload vertexmeshbuffer?
4553         }
4554 }
4555
4556 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4557 {
4558         dp_model_t *model = ent->model;
4559         int numvertices;
4560         // see if it's already cached this frame
4561         if (ent->animcache_vertex3f)
4562         {
4563                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4564                 if (wantnormals || wanttangents)
4565                 {
4566                         if (ent->animcache_normal3f)
4567                                 wantnormals = false;
4568                         if (ent->animcache_svector3f)
4569                                 wanttangents = false;
4570                         if (wantnormals || wanttangents)
4571                         {
4572                                 numvertices = model->surfmesh.num_vertices;
4573                                 if (wantnormals)
4574                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4575                                 if (wanttangents)
4576                                 {
4577                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4578                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4579                                 }
4580                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4581                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4582                         }
4583                 }
4584         }
4585         else
4586         {
4587                 // see if this ent is worth caching
4588                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4589                         return false;
4590                 // get some memory for this entity and generate mesh data
4591                 numvertices = model->surfmesh.num_vertices;
4592                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4593                 if (wantnormals)
4594                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4595                 if (wanttangents)
4596                 {
4597                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4598                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4599                 }
4600                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4601                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4602         }
4603         return true;
4604 }
4605
4606 void R_AnimCache_CacheVisibleEntities(void)
4607 {
4608         int i;
4609         qboolean wantnormals = true;
4610         qboolean wanttangents = !r_showsurfaces.integer;
4611
4612         switch(vid.renderpath)
4613         {
4614         case RENDERPATH_GL20:
4615         case RENDERPATH_D3D9:
4616         case RENDERPATH_D3D10:
4617         case RENDERPATH_D3D11:
4618         case RENDERPATH_GLES2:
4619                 break;
4620         case RENDERPATH_GL11:
4621         case RENDERPATH_GL13:
4622         case RENDERPATH_GLES1:
4623                 wanttangents = false;
4624                 break;
4625         case RENDERPATH_SOFT:
4626                 break;
4627         }
4628
4629         if (r_shownormals.integer)
4630                 wanttangents = wantnormals = true;
4631
4632         // TODO: thread this
4633         // NOTE: R_PrepareRTLights() also caches entities
4634
4635         for (i = 0;i < r_refdef.scene.numentities;i++)
4636                 if (r_refdef.viewcache.entityvisible[i])
4637                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4638 }
4639
4640 //==================================================================================
4641
4642 extern cvar_t r_overheadsprites_pushback;
4643
4644 static void R_View_UpdateEntityLighting (void)
4645 {
4646         int i;
4647         entity_render_t *ent;
4648         vec3_t tempdiffusenormal, avg;
4649         vec_t f, fa, fd, fdd;
4650         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4651
4652         for (i = 0;i < r_refdef.scene.numentities;i++)
4653         {
4654                 ent = r_refdef.scene.entities[i];
4655
4656                 // skip unseen models
4657                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4658                         continue;
4659
4660                 // skip bsp models
4661                 if (ent->model && ent->model->brush.num_leafs)
4662                 {
4663                         // TODO: use modellight for r_ambient settings on world?
4664                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4665                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4666                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4667                         continue;
4668                 }
4669
4670                 // fetch the lighting from the worldmodel data
4671                 VectorClear(ent->modellight_ambient);
4672                 VectorClear(ent->modellight_diffuse);
4673                 VectorClear(tempdiffusenormal);
4674                 if (ent->flags & RENDER_LIGHT)
4675                 {
4676                         vec3_t org;
4677                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4678
4679                         // complete lightning for lit sprites
4680                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4681                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4682                         {
4683                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4684                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4685                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4686                         }
4687                         else
4688                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4689
4690                         if(ent->flags & RENDER_EQUALIZE)
4691                         {
4692                                 // first fix up ambient lighting...
4693                                 if(r_equalize_entities_minambient.value > 0)
4694                                 {
4695                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4696                                         if(fd > 0)
4697                                         {
4698                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4699                                                 if(fa < r_equalize_entities_minambient.value * fd)
4700                                                 {
4701                                                         // solve:
4702                                                         //   fa'/fd' = minambient
4703                                                         //   fa'+0.25*fd' = fa+0.25*fd
4704                                                         //   ...
4705                                                         //   fa' = fd' * minambient
4706                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4707                                                         //   ...
4708                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4709                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4710                                                         //   ...
4711                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4712                                                         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
4713                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4714                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4715                                                 }
4716                                         }
4717                                 }
4718
4719                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4720                                 {
4721                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4722                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4723                                         f = fa + 0.25 * fd;
4724                                         if(f > 0)
4725                                         {
4726                                                 // adjust brightness and saturation to target
4727                                                 avg[0] = avg[1] = avg[2] = fa / f;
4728                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4729                                                 avg[0] = avg[1] = avg[2] = fd / f;
4730                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4731                                         }
4732                                 }
4733                         }
4734                 }
4735                 else // highly rare
4736                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4737
4738                 // move the light direction into modelspace coordinates for lighting code
4739                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4740                 if(VectorLength2(ent->modellight_lightdir) == 0)
4741                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4742                 VectorNormalize(ent->modellight_lightdir);
4743         }
4744 }
4745
4746 #define MAX_LINEOFSIGHTTRACES 64
4747
4748 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4749 {
4750         int i;
4751         vec3_t boxmins, boxmaxs;
4752         vec3_t start;
4753         vec3_t end;
4754         dp_model_t *model = r_refdef.scene.worldmodel;
4755
4756         if (!model || !model->brush.TraceLineOfSight)
4757                 return true;
4758
4759         // expand the box a little
4760         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4761         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4762         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4763         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4764         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4765         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4766
4767         // return true if eye is inside enlarged box
4768         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4769                 return true;
4770
4771         // try center
4772         VectorCopy(eye, start);
4773         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4774         if (model->brush.TraceLineOfSight(model, start, end))
4775                 return true;
4776
4777         // try various random positions
4778         for (i = 0;i < numsamples;i++)
4779         {
4780                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4781                 if (model->brush.TraceLineOfSight(model, start, end))
4782                         return true;
4783         }
4784
4785         return false;
4786 }
4787
4788
4789 static void R_View_UpdateEntityVisible (void)
4790 {
4791         int i;
4792         int renderimask;
4793         int samples;
4794         entity_render_t *ent;
4795
4796         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4797                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4798                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4799                 :                                                          RENDER_EXTERIORMODEL;
4800         if (!r_drawviewmodel.integer)
4801                 renderimask |= RENDER_VIEWMODEL;
4802         if (!r_drawexteriormodel.integer)
4803                 renderimask |= RENDER_EXTERIORMODEL;
4804         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4805         {
4806                 // worldmodel can check visibility
4807                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4808                 for (i = 0;i < r_refdef.scene.numentities;i++)
4809                 {
4810                         ent = r_refdef.scene.entities[i];
4811                         if (!(ent->flags & renderimask))
4812                         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)))
4813                         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))
4814                                 r_refdef.viewcache.entityvisible[i] = true;
4815                 }
4816         }
4817         else
4818         {
4819                 // no worldmodel or it can't check visibility
4820                 for (i = 0;i < r_refdef.scene.numentities;i++)
4821                 {
4822                         ent = r_refdef.scene.entities[i];
4823                         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));
4824                 }
4825         }
4826         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4827                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4828         {
4829                 for (i = 0;i < r_refdef.scene.numentities;i++)
4830                 {
4831                         if (!r_refdef.viewcache.entityvisible[i])
4832                                 continue;
4833                         ent = r_refdef.scene.entities[i];
4834                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4835                         {
4836                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4837                                 if (samples < 0)
4838                                         continue; // temp entities do pvs only
4839                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4840                                         ent->last_trace_visibility = realtime;
4841                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4842                                         r_refdef.viewcache.entityvisible[i] = 0;
4843                         }
4844                 }
4845         }
4846 }
4847
4848 /// only used if skyrendermasked, and normally returns false
4849 int R_DrawBrushModelsSky (void)
4850 {
4851         int i, sky;
4852         entity_render_t *ent;
4853
4854         sky = false;
4855         for (i = 0;i < r_refdef.scene.numentities;i++)
4856         {
4857                 if (!r_refdef.viewcache.entityvisible[i])
4858                         continue;
4859                 ent = r_refdef.scene.entities[i];
4860                 if (!ent->model || !ent->model->DrawSky)
4861                         continue;
4862                 ent->model->DrawSky(ent);
4863                 sky = true;
4864         }
4865         return sky;
4866 }
4867
4868 static void R_DrawNoModel(entity_render_t *ent);
4869 static void R_DrawModels(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 if (!r_refdef.viewcache.entityvisible[i])
4877                         continue;
4878                 ent = r_refdef.scene.entities[i];
4879                 r_refdef.stats.entities++;
4880                 /*
4881                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4882                 {
4883                         vec3_t f, l, u, o;
4884                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4885                         Con_Printf("R_DrawModels\n");
4886                         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]);
4887                         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);
4888                         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);
4889                 }
4890                 */
4891                 if (ent->model && ent->model->Draw != NULL)
4892                         ent->model->Draw(ent);
4893                 else
4894                         R_DrawNoModel(ent);
4895         }
4896 }
4897
4898 static void R_DrawModelsDepth(void)
4899 {
4900         int i;
4901         entity_render_t *ent;
4902
4903         for (i = 0;i < r_refdef.scene.numentities;i++)
4904         {
4905                 if (!r_refdef.viewcache.entityvisible[i])
4906                         continue;
4907                 ent = r_refdef.scene.entities[i];
4908                 if (ent->model && ent->model->DrawDepth != NULL)
4909                         ent->model->DrawDepth(ent);
4910         }
4911 }
4912
4913 static void R_DrawModelsDebug(void)
4914 {
4915         int i;
4916         entity_render_t *ent;
4917
4918         for (i = 0;i < r_refdef.scene.numentities;i++)
4919         {
4920                 if (!r_refdef.viewcache.entityvisible[i])
4921                         continue;
4922                 ent = r_refdef.scene.entities[i];
4923                 if (ent->model && ent->model->DrawDebug != NULL)
4924                         ent->model->DrawDebug(ent);
4925         }
4926 }
4927
4928 static void R_DrawModelsAddWaterPlanes(void)
4929 {
4930         int i;
4931         entity_render_t *ent;
4932
4933         for (i = 0;i < r_refdef.scene.numentities;i++)
4934         {
4935                 if (!r_refdef.viewcache.entityvisible[i])
4936                         continue;
4937                 ent = r_refdef.scene.entities[i];
4938                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4939                         ent->model->DrawAddWaterPlanes(ent);
4940         }
4941 }
4942
4943 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4944 {
4945         if (r_hdr_irisadaptation.integer)
4946         {
4947                 vec3_t ambient;
4948                 vec3_t diffuse;
4949                 vec3_t diffusenormal;
4950                 vec_t brightness;
4951                 vec_t goal;
4952                 vec_t adjust;
4953                 vec_t current;
4954                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4955                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4956                 brightness = max(0.0000001f, brightness);
4957                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4958                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4959                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4960                 current = r_hdr_irisadaptation_value.value;
4961                 if (current < goal)
4962                         current = min(current + adjust, goal);
4963                 else if (current > goal)
4964                         current = max(current - adjust, goal);
4965                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4966                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4967         }
4968         else if (r_hdr_irisadaptation_value.value != 1.0f)
4969                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4970 }
4971
4972 static void R_View_SetFrustum(const int *scissor)
4973 {
4974         int i;
4975         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4976         vec3_t forward, left, up, origin, v;
4977
4978         if(scissor)
4979         {
4980                 // flipped x coordinates (because x points left here)
4981                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4982                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4983
4984                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4985                 switch(vid.renderpath)
4986                 {
4987                         case RENDERPATH_D3D9:
4988                         case RENDERPATH_D3D10:
4989                         case RENDERPATH_D3D11:
4990                                 // non-flipped y coordinates
4991                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4992                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4993                                 break;
4994                         case RENDERPATH_SOFT:
4995                         case RENDERPATH_GL11:
4996                         case RENDERPATH_GL13:
4997                         case RENDERPATH_GL20:
4998                         case RENDERPATH_GLES1:
4999                         case RENDERPATH_GLES2:
5000                                 // non-flipped y coordinates
5001                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5002                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5003                                 break;
5004                 }
5005         }
5006
5007         // we can't trust r_refdef.view.forward and friends in reflected scenes
5008         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5009
5010 #if 0
5011         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5012         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5013         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5014         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5015         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5016         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5017         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5018         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5019         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5020         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5021         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5022         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5023 #endif
5024
5025 #if 0
5026         zNear = r_refdef.nearclip;
5027         nudge = 1.0 - 1.0 / (1<<23);
5028         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5029         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5030         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5031         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5032         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5033         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5034         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5035         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5036 #endif
5037
5038
5039
5040 #if 0
5041         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5042         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5043         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5044         r_refdef.view.frustum[0].dist = m[15] - m[12];
5045
5046         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5047         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5048         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5049         r_refdef.view.frustum[1].dist = m[15] + m[12];
5050
5051         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5052         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5053         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5054         r_refdef.view.frustum[2].dist = m[15] - m[13];
5055
5056         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5057         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5058         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5059         r_refdef.view.frustum[3].dist = m[15] + m[13];
5060
5061         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5062         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5063         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5064         r_refdef.view.frustum[4].dist = m[15] - m[14];
5065
5066         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5067         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5068         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5069         r_refdef.view.frustum[5].dist = m[15] + m[14];
5070 #endif
5071
5072         if (r_refdef.view.useperspective)
5073         {
5074                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5075                 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]);
5076                 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]);
5077                 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]);
5078                 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]);
5079
5080                 // then the normals from the corners relative to origin
5081                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5082                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5083                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5084                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5085
5086                 // in a NORMAL view, forward cross left == up
5087                 // in a REFLECTED view, forward cross left == down
5088                 // so our cross products above need to be adjusted for a left handed coordinate system
5089                 CrossProduct(forward, left, v);
5090                 if(DotProduct(v, up) < 0)
5091                 {
5092                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5093                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5094                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5095                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5096                 }
5097
5098                 // Leaving those out was a mistake, those were in the old code, and they
5099                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5100                 // I couldn't reproduce it after adding those normalizations. --blub
5101                 VectorNormalize(r_refdef.view.frustum[0].normal);
5102                 VectorNormalize(r_refdef.view.frustum[1].normal);
5103                 VectorNormalize(r_refdef.view.frustum[2].normal);
5104                 VectorNormalize(r_refdef.view.frustum[3].normal);
5105
5106                 // make the corners absolute
5107                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5108                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5109                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5110                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5111
5112                 // one more normal
5113                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5114
5115                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5116                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5117                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5118                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5119                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5120         }
5121         else
5122         {
5123                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5124                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5125                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5126                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5127                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5128                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5129                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5130                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5131                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5132                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5133         }
5134         r_refdef.view.numfrustumplanes = 5;
5135
5136         if (r_refdef.view.useclipplane)
5137         {
5138                 r_refdef.view.numfrustumplanes = 6;
5139                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5140         }
5141
5142         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5143                 PlaneClassify(r_refdef.view.frustum + i);
5144
5145         // LordHavoc: note to all quake engine coders, Quake had a special case
5146         // for 90 degrees which assumed a square view (wrong), so I removed it,
5147         // Quake2 has it disabled as well.
5148
5149         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5150         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5151         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5152         //PlaneClassify(&frustum[0]);
5153
5154         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5155         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5156         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5157         //PlaneClassify(&frustum[1]);
5158
5159         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5160         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5161         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5162         //PlaneClassify(&frustum[2]);
5163
5164         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5165         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5166         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5167         //PlaneClassify(&frustum[3]);
5168
5169         // nearclip plane
5170         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5171         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5172         //PlaneClassify(&frustum[4]);
5173 }
5174
5175 void R_View_UpdateWithScissor(const int *myscissor)
5176 {
5177         R_Main_ResizeViewCache();
5178         R_View_SetFrustum(myscissor);
5179         R_View_WorldVisibility(r_refdef.view.useclipplane);
5180         R_View_UpdateEntityVisible();
5181         R_View_UpdateEntityLighting();
5182 }
5183
5184 void R_View_Update(void)
5185 {
5186         R_Main_ResizeViewCache();
5187         R_View_SetFrustum(NULL);
5188         R_View_WorldVisibility(r_refdef.view.useclipplane);
5189         R_View_UpdateEntityVisible();
5190         R_View_UpdateEntityLighting();
5191 }
5192
5193 float viewscalefpsadjusted = 1.0f;
5194
5195 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5196 {
5197         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5198         scale = bound(0.03125f, scale, 1.0f);
5199         *outwidth = (int)ceil(width * scale);
5200         *outheight = (int)ceil(height * scale);
5201 }
5202
5203 void R_Mesh_SetMainRenderTargets(void)
5204 {
5205         if (r_bloomstate.fbo_framebuffer)
5206                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5207         else
5208                 R_Mesh_ResetRenderTargets();
5209 }
5210
5211 void R_SetupView(qboolean allowwaterclippingplane)
5212 {
5213         const float *customclipplane = NULL;
5214         float plane[4];
5215         int scaledwidth, scaledheight;
5216         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5217         {
5218                 // LordHavoc: couldn't figure out how to make this approach the
5219                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5220                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5221                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5222                         dist = r_refdef.view.clipplane.dist;
5223                 plane[0] = r_refdef.view.clipplane.normal[0];
5224                 plane[1] = r_refdef.view.clipplane.normal[1];
5225                 plane[2] = r_refdef.view.clipplane.normal[2];
5226                 plane[3] = -dist;
5227                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5228         }
5229
5230         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5231         if (!r_refdef.view.useperspective)
5232                 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);
5233         else if (vid.stencil && r_useinfinitefarclip.integer)
5234                 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);
5235         else
5236                 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);
5237         R_Mesh_SetMainRenderTargets();
5238         R_SetViewport(&r_refdef.view.viewport);
5239         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5240         {
5241                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5242                 float screenplane[4];
5243                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5244                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5245                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5246                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5247                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5248         }
5249 }
5250
5251 void R_EntityMatrix(const matrix4x4_t *matrix)
5252 {
5253         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5254         {
5255                 gl_modelmatrixchanged = false;
5256                 gl_modelmatrix = *matrix;
5257                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5258                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5259                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5260                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5261                 CHECKGLERROR
5262                 switch(vid.renderpath)
5263                 {
5264                 case RENDERPATH_D3D9:
5265 #ifdef SUPPORTD3D
5266                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5267                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5268 #endif
5269                         break;
5270                 case RENDERPATH_D3D10:
5271                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5272                         break;
5273                 case RENDERPATH_D3D11:
5274                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5275                         break;
5276                 case RENDERPATH_GL11:
5277                 case RENDERPATH_GL13:
5278                 case RENDERPATH_GLES1:
5279                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5280                         break;
5281                 case RENDERPATH_SOFT:
5282                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5283                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5284                         break;
5285                 case RENDERPATH_GL20:
5286                 case RENDERPATH_GLES2:
5287                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5288                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5289                         break;
5290                 }
5291         }
5292 }
5293
5294 void R_ResetViewRendering2D(void)
5295 {
5296         r_viewport_t viewport;
5297         DrawQ_Finish();
5298
5299         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5300         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);
5301         R_Mesh_ResetRenderTargets();
5302         R_SetViewport(&viewport);
5303         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5304         GL_Color(1, 1, 1, 1);
5305         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5306         GL_BlendFunc(GL_ONE, GL_ZERO);
5307         GL_ScissorTest(false);
5308         GL_DepthMask(false);
5309         GL_DepthRange(0, 1);
5310         GL_DepthTest(false);
5311         GL_DepthFunc(GL_LEQUAL);
5312         R_EntityMatrix(&identitymatrix);
5313         R_Mesh_ResetTextureState();
5314         GL_PolygonOffset(0, 0);
5315         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5316         switch(vid.renderpath)
5317         {
5318         case RENDERPATH_GL11:
5319         case RENDERPATH_GL13:
5320         case RENDERPATH_GL20:
5321         case RENDERPATH_GLES1:
5322         case RENDERPATH_GLES2:
5323                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5324                 break;
5325         case RENDERPATH_D3D9:
5326         case RENDERPATH_D3D10:
5327         case RENDERPATH_D3D11:
5328         case RENDERPATH_SOFT:
5329                 break;
5330         }
5331         GL_CullFace(GL_NONE);
5332 }
5333
5334 void R_ResetViewRendering3D(void)
5335 {
5336         DrawQ_Finish();
5337
5338         R_SetupView(true);
5339         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5340         GL_Color(1, 1, 1, 1);
5341         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5342         GL_BlendFunc(GL_ONE, GL_ZERO);
5343         GL_ScissorTest(true);
5344         GL_DepthMask(true);
5345         GL_DepthRange(0, 1);
5346         GL_DepthTest(true);
5347         GL_DepthFunc(GL_LEQUAL);
5348         R_EntityMatrix(&identitymatrix);
5349         R_Mesh_ResetTextureState();
5350         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5351         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5352         switch(vid.renderpath)
5353         {
5354         case RENDERPATH_GL11:
5355         case RENDERPATH_GL13:
5356         case RENDERPATH_GL20:
5357         case RENDERPATH_GLES1:
5358         case RENDERPATH_GLES2:
5359                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5360                 break;
5361         case RENDERPATH_D3D9:
5362         case RENDERPATH_D3D10:
5363         case RENDERPATH_D3D11:
5364         case RENDERPATH_SOFT:
5365                 break;
5366         }
5367         GL_CullFace(r_refdef.view.cullface_back);
5368 }
5369
5370 /*
5371 ================
5372 R_RenderView_UpdateViewVectors
5373 ================
5374 */
5375 static void R_RenderView_UpdateViewVectors(void)
5376 {
5377         // break apart the view matrix into vectors for various purposes
5378         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5379         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5380         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5381         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5382         // make an inverted copy of the view matrix for tracking sprites
5383         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5384 }
5385
5386 void R_RenderScene(void);
5387 void R_RenderWaterPlanes(void);
5388
5389 static void R_Water_StartFrame(void)
5390 {
5391         int i;
5392         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5393         r_waterstate_waterplane_t *p;
5394
5395         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5396                 return;
5397
5398         switch(vid.renderpath)
5399         {
5400         case RENDERPATH_GL20:
5401         case RENDERPATH_D3D9:
5402         case RENDERPATH_D3D10:
5403         case RENDERPATH_D3D11:
5404         case RENDERPATH_SOFT:
5405         case RENDERPATH_GLES2:
5406                 break;
5407         case RENDERPATH_GL11:
5408         case RENDERPATH_GL13:
5409         case RENDERPATH_GLES1:
5410                 return;
5411         }
5412
5413         // set waterwidth and waterheight to the water resolution that will be
5414         // used (often less than the screen resolution for faster rendering)
5415         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5416
5417         // calculate desired texture sizes
5418         // can't use water if the card does not support the texture size
5419         if (!r_water.integer || r_showsurfaces.integer)
5420                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5421         else if (vid.support.arb_texture_non_power_of_two)
5422         {
5423                 texturewidth = waterwidth;
5424                 textureheight = waterheight;
5425                 camerawidth = waterwidth;
5426                 cameraheight = waterheight;
5427         }
5428         else
5429         {
5430                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5431                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5432                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5433                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5434         }
5435
5436         // allocate textures as needed
5437         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5438         {
5439                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5440                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5441                 {
5442                         if (p->texture_refraction)
5443                                 R_FreeTexture(p->texture_refraction);
5444                         p->texture_refraction = NULL;
5445                         if (p->texture_reflection)
5446                                 R_FreeTexture(p->texture_reflection);
5447                         p->texture_reflection = NULL;
5448                         if (p->texture_camera)
5449                                 R_FreeTexture(p->texture_camera);
5450                         p->texture_camera = NULL;
5451                 }
5452                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5453                 r_waterstate.texturewidth = texturewidth;
5454                 r_waterstate.textureheight = textureheight;
5455                 r_waterstate.camerawidth = camerawidth;
5456                 r_waterstate.cameraheight = cameraheight;
5457         }
5458
5459         if (r_waterstate.texturewidth)
5460         {
5461                 int scaledwidth, scaledheight;
5462
5463                 r_waterstate.enabled = true;
5464
5465                 // when doing a reduced render (HDR) we want to use a smaller area
5466                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5467                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5468                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5469
5470                 // set up variables that will be used in shader setup
5471                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5472                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5473                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5474                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5475         }
5476
5477         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5478         r_waterstate.numwaterplanes = 0;
5479 }
5480
5481 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5482 {
5483         int triangleindex, planeindex;
5484         const int *e;
5485         vec3_t vert[3];
5486         vec3_t normal;
5487         vec3_t center;
5488         mplane_t plane;
5489         r_waterstate_waterplane_t *p;
5490         texture_t *t = R_GetCurrentTexture(surface->texture);
5491
5492         // just use the first triangle with a valid normal for any decisions
5493         VectorClear(normal);
5494         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5495         {
5496                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5497                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5498                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5499                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5500                 if (VectorLength2(normal) >= 0.001)
5501                         break;
5502         }
5503
5504         VectorCopy(normal, plane.normal);
5505         VectorNormalize(plane.normal);
5506         plane.dist = DotProduct(vert[0], plane.normal);
5507         PlaneClassify(&plane);
5508         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5509         {
5510                 // skip backfaces (except if nocullface is set)
5511                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5512                         return;
5513                 VectorNegate(plane.normal, plane.normal);
5514                 plane.dist *= -1;
5515                 PlaneClassify(&plane);
5516         }
5517
5518
5519         // find a matching plane if there is one
5520         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5521                 if(p->camera_entity == t->camera_entity)
5522                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5523                                 break;
5524         if (planeindex >= r_waterstate.maxwaterplanes)
5525                 return; // nothing we can do, out of planes
5526
5527         // if this triangle does not fit any known plane rendered this frame, add one
5528         if (planeindex >= r_waterstate.numwaterplanes)
5529         {
5530                 // store the new plane
5531                 r_waterstate.numwaterplanes++;
5532                 p->plane = plane;
5533                 // clear materialflags and pvs
5534                 p->materialflags = 0;
5535                 p->pvsvalid = false;
5536                 p->camera_entity = t->camera_entity;
5537                 VectorCopy(surface->mins, p->mins);
5538                 VectorCopy(surface->maxs, p->maxs);
5539         }
5540         else
5541         {
5542                 // merge mins/maxs
5543                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5544                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5545                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5546                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5547                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5548                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5549         }
5550         // merge this surface's materialflags into the waterplane
5551         p->materialflags |= t->currentmaterialflags;
5552         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5553         {
5554                 // merge this surface's PVS into the waterplane
5555                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5556                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5557                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5558                 {
5559                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5560                         p->pvsvalid = true;
5561                 }
5562         }
5563 }
5564
5565 extern cvar_t r_drawparticles;
5566 extern cvar_t r_drawdecals;
5567
5568 static void R_Water_ProcessPlanes(void)
5569 {
5570         int myscissor[4];
5571         r_refdef_view_t originalview;
5572         r_refdef_view_t myview;
5573         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5574         r_waterstate_waterplane_t *p;
5575         vec3_t visorigin;
5576
5577         originalview = r_refdef.view;
5578
5579         // lowquality hack, temporarily shut down some cvars and restore afterwards
5580         qualityreduction = r_water_lowquality.integer;
5581         if (qualityreduction > 0)
5582         {
5583                 if (qualityreduction >= 1)
5584                 {
5585                         old_r_shadows = r_shadows.integer;
5586                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5587                         old_r_dlight = r_shadow_realtime_dlight.integer;
5588                         Cvar_SetValueQuick(&r_shadows, 0);
5589                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5590                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5591                 }
5592                 if (qualityreduction >= 2)
5593                 {
5594                         old_r_dynamic = r_dynamic.integer;
5595                         old_r_particles = r_drawparticles.integer;
5596                         old_r_decals = r_drawdecals.integer;
5597                         Cvar_SetValueQuick(&r_dynamic, 0);
5598                         Cvar_SetValueQuick(&r_drawparticles, 0);
5599                         Cvar_SetValueQuick(&r_drawdecals, 0);
5600                 }
5601         }
5602
5603         // make sure enough textures are allocated
5604         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5605         {
5606                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5607                 {
5608                         if (!p->texture_refraction)
5609                                 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);
5610                         if (!p->texture_refraction)
5611                                 goto error;
5612                 }
5613                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5614                 {
5615                         if (!p->texture_camera)
5616                                 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);
5617                         if (!p->texture_camera)
5618                                 goto error;
5619                 }
5620
5621                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5622                 {
5623                         if (!p->texture_reflection)
5624                                 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);
5625                         if (!p->texture_reflection)
5626                                 goto error;
5627                 }
5628         }
5629
5630         // render views
5631         r_refdef.view = originalview;
5632         r_refdef.view.showdebug = false;
5633         r_refdef.view.width = r_waterstate.waterwidth;
5634         r_refdef.view.height = r_waterstate.waterheight;
5635         r_refdef.view.useclipplane = true;
5636         myview = r_refdef.view;
5637         r_waterstate.renderingscene = true;
5638         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5639         {
5640                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5641                 {
5642                         r_refdef.view = myview;
5643                         if(r_water_scissormode.integer)
5644                         {
5645                                 R_SetupView(true);
5646                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5647                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5648                         }
5649
5650                         // render reflected scene and copy into texture
5651                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5652                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5653                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5654                         r_refdef.view.clipplane = p->plane;
5655                         // reverse the cullface settings for this render
5656                         r_refdef.view.cullface_front = GL_FRONT;
5657                         r_refdef.view.cullface_back = GL_BACK;
5658                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5659                         {
5660                                 r_refdef.view.usecustompvs = true;
5661                                 if (p->pvsvalid)
5662                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5663                                 else
5664                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5665                         }
5666
5667                         R_ResetViewRendering3D();
5668                         R_ClearScreen(r_refdef.fogenabled);
5669                         if(r_water_scissormode.integer & 2)
5670                                 R_View_UpdateWithScissor(myscissor);
5671                         else
5672                                 R_View_Update();
5673                         if(r_water_scissormode.integer & 1)
5674                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5675                         R_RenderScene();
5676
5677                         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);
5678                 }
5679
5680                 // render the normal view scene and copy into texture
5681                 // (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)
5682                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5683                 {
5684                         r_refdef.view = myview;
5685                         if(r_water_scissormode.integer)
5686                         {
5687                                 R_SetupView(true);
5688                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5689                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5690                         }
5691
5692                         r_waterstate.renderingrefraction = true;
5693
5694                         r_refdef.view.clipplane = p->plane;
5695                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5696                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5697
5698                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5699                         {
5700                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5701                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5702                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5703                                 R_RenderView_UpdateViewVectors();
5704                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5705                                 {
5706                                         r_refdef.view.usecustompvs = true;
5707                                         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);
5708                                 }
5709                         }
5710
5711                         PlaneClassify(&r_refdef.view.clipplane);
5712
5713                         R_ResetViewRendering3D();
5714                         R_ClearScreen(r_refdef.fogenabled);
5715                         if(r_water_scissormode.integer & 2)
5716                                 R_View_UpdateWithScissor(myscissor);
5717                         else
5718                                 R_View_Update();
5719                         if(r_water_scissormode.integer & 1)
5720                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5721                         R_RenderScene();
5722
5723                         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);
5724                         r_waterstate.renderingrefraction = false;
5725                 }
5726                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5727                 {
5728                         r_refdef.view = myview;
5729
5730                         r_refdef.view.clipplane = p->plane;
5731                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5732                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5733
5734                         r_refdef.view.width = r_waterstate.camerawidth;
5735                         r_refdef.view.height = r_waterstate.cameraheight;
5736                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5737                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5738
5739                         if(p->camera_entity)
5740                         {
5741                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5742                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5743                         }
5744
5745                         // note: all of the view is used for displaying... so
5746                         // there is no use in scissoring
5747
5748                         // reverse the cullface settings for this render
5749                         r_refdef.view.cullface_front = GL_FRONT;
5750                         r_refdef.view.cullface_back = GL_BACK;
5751                         // also reverse the view matrix
5752                         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
5753                         R_RenderView_UpdateViewVectors();
5754                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5755                         {
5756                                 r_refdef.view.usecustompvs = true;
5757                                 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);
5758                         }
5759                         
5760                         // camera needs no clipplane
5761                         r_refdef.view.useclipplane = false;
5762
5763                         PlaneClassify(&r_refdef.view.clipplane);
5764
5765                         R_ResetViewRendering3D();
5766                         R_ClearScreen(r_refdef.fogenabled);
5767                         R_View_Update();
5768                         R_RenderScene();
5769
5770                         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);
5771                         r_waterstate.renderingrefraction = false;
5772                 }
5773
5774         }
5775         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5776         r_waterstate.renderingscene = false;
5777         r_refdef.view = originalview;
5778         R_ResetViewRendering3D();
5779         R_ClearScreen(r_refdef.fogenabled);
5780         R_View_Update();
5781         goto finish;
5782 error:
5783         r_refdef.view = originalview;
5784         r_waterstate.renderingscene = false;
5785         Cvar_SetValueQuick(&r_water, 0);
5786         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5787 finish:
5788         // lowquality hack, restore cvars
5789         if (qualityreduction > 0)
5790         {
5791                 if (qualityreduction >= 1)
5792                 {
5793                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5794                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5795                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5796                 }
5797                 if (qualityreduction >= 2)
5798                 {
5799                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5800                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5801                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5802                 }
5803         }
5804 }
5805
5806 void R_Bloom_StartFrame(void)
5807 {
5808         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5809         int viewwidth, viewheight;
5810         textype_t textype;
5811
5812         if (r_viewscale_fpsscaling.integer)
5813         {
5814                 double actualframetime;
5815                 double targetframetime;
5816                 double adjust;
5817                 actualframetime = r_refdef.lastdrawscreentime;
5818                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5819                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5820                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5821                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5822                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5823                 viewscalefpsadjusted += adjust;
5824                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5825         }
5826         else
5827                 viewscalefpsadjusted = 1.0f;
5828
5829         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5830
5831         switch(vid.renderpath)
5832         {
5833         case RENDERPATH_GL20:
5834         case RENDERPATH_D3D9:
5835         case RENDERPATH_D3D10:
5836         case RENDERPATH_D3D11:
5837         case RENDERPATH_SOFT:
5838         case RENDERPATH_GLES2:
5839                 break;
5840         case RENDERPATH_GL11:
5841         case RENDERPATH_GL13:
5842         case RENDERPATH_GLES1:
5843                 return;
5844         }
5845
5846         // set bloomwidth and bloomheight to the bloom resolution that will be
5847         // used (often less than the screen resolution for faster rendering)
5848         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5849         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5850         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5851         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5852         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5853
5854         // calculate desired texture sizes
5855         if (vid.support.arb_texture_non_power_of_two)
5856         {
5857                 screentexturewidth = vid.width;
5858                 screentextureheight = vid.height;
5859                 bloomtexturewidth = r_bloomstate.bloomwidth;
5860                 bloomtextureheight = r_bloomstate.bloomheight;
5861         }
5862         else
5863         {
5864                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5865                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5866                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5867                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5868         }
5869
5870         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))
5871         {
5872                 Cvar_SetValueQuick(&r_hdr, 0);
5873                 Cvar_SetValueQuick(&r_bloom, 0);
5874                 Cvar_SetValueQuick(&r_motionblur, 0);
5875                 Cvar_SetValueQuick(&r_damageblur, 0);
5876         }
5877
5878         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)
5879                 screentexturewidth = screentextureheight = 0;
5880         if (!r_hdr.integer && !r_bloom.integer)
5881                 bloomtexturewidth = bloomtextureheight = 0;
5882
5883         textype = TEXTYPE_COLORBUFFER;
5884         switch (vid.renderpath)
5885         {
5886         case RENDERPATH_GL20:
5887         case RENDERPATH_GLES2:
5888                 if (vid.support.ext_framebuffer_object)
5889                 {
5890                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5891                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5892                 }
5893                 break;
5894         case RENDERPATH_GL11:
5895         case RENDERPATH_GL13:
5896         case RENDERPATH_GLES1:
5897         case RENDERPATH_D3D9:
5898         case RENDERPATH_D3D10:
5899         case RENDERPATH_D3D11:
5900         case RENDERPATH_SOFT:
5901                 break;
5902         }
5903
5904         // allocate textures as needed
5905         if (r_bloomstate.screentexturewidth != screentexturewidth
5906          || r_bloomstate.screentextureheight != screentextureheight
5907          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5908          || r_bloomstate.bloomtextureheight != bloomtextureheight
5909          || r_bloomstate.texturetype != textype
5910          || r_bloomstate.viewfbo != r_viewfbo.integer)
5911         {
5912                 if (r_bloomstate.texture_bloom)
5913                         R_FreeTexture(r_bloomstate.texture_bloom);
5914                 r_bloomstate.texture_bloom = NULL;
5915                 if (r_bloomstate.texture_screen)
5916                         R_FreeTexture(r_bloomstate.texture_screen);
5917                 r_bloomstate.texture_screen = NULL;
5918                 if (r_bloomstate.fbo_framebuffer)
5919                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5920                 r_bloomstate.fbo_framebuffer = 0;
5921                 if (r_bloomstate.texture_framebuffercolor)
5922                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5923                 r_bloomstate.texture_framebuffercolor = NULL;
5924                 if (r_bloomstate.texture_framebufferdepth)
5925                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5926                 r_bloomstate.texture_framebufferdepth = NULL;
5927                 r_bloomstate.screentexturewidth = screentexturewidth;
5928                 r_bloomstate.screentextureheight = screentextureheight;
5929                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5930                         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);
5931                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5932                 {
5933                         // FIXME: choose depth bits based on a cvar
5934                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5935                         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);
5936                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5937                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5938                         // render depth into one texture and normalmap into the other
5939                         if (qglDrawBuffer)
5940                         {
5941                                 int status;
5942                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5943                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5944                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5945                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5946                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5947                         }
5948                 }
5949                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5950                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5951                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5952                         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);
5953                 r_bloomstate.viewfbo = r_viewfbo.integer;
5954                 r_bloomstate.texturetype = textype;
5955         }
5956
5957         // when doing a reduced render (HDR) we want to use a smaller area
5958         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5959         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5960         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5961         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5962         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5963
5964         // set up a texcoord array for the full resolution screen image
5965         // (we have to keep this around to copy back during final render)
5966         r_bloomstate.screentexcoord2f[0] = 0;
5967         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5968         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5969         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5970         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5971         r_bloomstate.screentexcoord2f[5] = 0;
5972         r_bloomstate.screentexcoord2f[6] = 0;
5973         r_bloomstate.screentexcoord2f[7] = 0;
5974
5975         // set up a texcoord array for the reduced resolution bloom image
5976         // (which will be additive blended over the screen image)
5977         r_bloomstate.bloomtexcoord2f[0] = 0;
5978         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5979         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5980         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5981         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5982         r_bloomstate.bloomtexcoord2f[5] = 0;
5983         r_bloomstate.bloomtexcoord2f[6] = 0;
5984         r_bloomstate.bloomtexcoord2f[7] = 0;
5985
5986         switch(vid.renderpath)
5987         {
5988         case RENDERPATH_GL11:
5989         case RENDERPATH_GL13:
5990         case RENDERPATH_GL20:
5991         case RENDERPATH_SOFT:
5992         case RENDERPATH_GLES1:
5993         case RENDERPATH_GLES2:
5994                 break;
5995         case RENDERPATH_D3D9:
5996         case RENDERPATH_D3D10:
5997         case RENDERPATH_D3D11:
5998                 {
5999                         int i;
6000                         for (i = 0;i < 4;i++)
6001                         {
6002                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6003                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6004                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6005                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6006                         }
6007                 }
6008                 break;
6009         }
6010
6011         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6012         {
6013                 r_bloomstate.enabled = true;
6014                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6015         }
6016
6017         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);
6018
6019         if (r_bloomstate.fbo_framebuffer)
6020                 r_refdef.view.clear = true;
6021 }
6022
6023 void R_Bloom_CopyBloomTexture(float colorscale)
6024 {
6025         r_refdef.stats.bloom++;
6026
6027         // scale down screen texture to the bloom texture size
6028         CHECKGLERROR
6029         R_Mesh_SetMainRenderTargets();
6030         R_SetViewport(&r_bloomstate.viewport);
6031         GL_BlendFunc(GL_ONE, GL_ZERO);
6032         GL_Color(colorscale, colorscale, colorscale, 1);
6033         // 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...
6034         switch(vid.renderpath)
6035         {
6036         case RENDERPATH_GL11:
6037         case RENDERPATH_GL13:
6038         case RENDERPATH_GL20:
6039         case RENDERPATH_GLES1:
6040         case RENDERPATH_GLES2:
6041         case RENDERPATH_SOFT:
6042                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6043                 break;
6044         case RENDERPATH_D3D9:
6045         case RENDERPATH_D3D10:
6046         case RENDERPATH_D3D11:
6047                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6048                 break;
6049         }
6050         // TODO: do boxfilter scale-down in shader?
6051         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6052         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6053         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6054
6055         // we now have a bloom image in the framebuffer
6056         // copy it into the bloom image texture for later processing
6057         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);
6058         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6059 }
6060
6061 void R_Bloom_CopyHDRTexture(void)
6062 {
6063         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);
6064         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6065 }
6066
6067 void R_Bloom_MakeTexture(void)
6068 {
6069         int x, range, dir;
6070         float xoffset, yoffset, r, brighten;
6071
6072         r_refdef.stats.bloom++;
6073
6074         R_ResetViewRendering2D();
6075
6076         // we have a bloom image in the framebuffer
6077         CHECKGLERROR
6078         R_SetViewport(&r_bloomstate.viewport);
6079
6080         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6081         {
6082                 x *= 2;
6083                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6084                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6085                 GL_Color(r,r,r,1);
6086                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6087                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6088                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6089                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6090
6091                 // copy the vertically blurred bloom view to a texture
6092                 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);
6093                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6094         }
6095
6096         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6097         brighten = r_bloom_brighten.value;
6098         if (r_bloomstate.hdr)
6099                 brighten *= r_hdr_range.value;
6100         brighten = sqrt(brighten);
6101         if(range >= 1)
6102                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6103         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6104
6105         for (dir = 0;dir < 2;dir++)
6106         {
6107                 // blend on at multiple vertical offsets to achieve a vertical blur
6108                 // TODO: do offset blends using GLSL
6109                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6110                 GL_BlendFunc(GL_ONE, GL_ZERO);
6111                 for (x = -range;x <= range;x++)
6112                 {
6113                         if (!dir){xoffset = 0;yoffset = x;}
6114                         else {xoffset = x;yoffset = 0;}
6115                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6116                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6117                         // compute a texcoord array with the specified x and y offset
6118                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6119                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6121                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6122                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6123                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6124                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6125                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6126                         // this r value looks like a 'dot' particle, fading sharply to
6127                         // black at the edges
6128                         // (probably not realistic but looks good enough)
6129                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6130                         //r = brighten/(range*2+1);
6131                         r = brighten / (range * 2 + 1);
6132                         if(range >= 1)
6133                                 r *= (1 - x*x/(float)(range*range));
6134                         GL_Color(r, r, r, 1);
6135                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6136                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6137                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6138                         GL_BlendFunc(GL_ONE, GL_ONE);
6139                 }
6140
6141                 // copy the vertically blurred bloom view to a texture
6142                 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);
6143                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6144         }
6145 }
6146
6147 void R_HDR_RenderBloomTexture(void)
6148 {
6149         int oldwidth, oldheight;
6150         float oldcolorscale;
6151         qboolean oldwaterstate;
6152
6153         oldwaterstate = r_waterstate.enabled;
6154         oldcolorscale = r_refdef.view.colorscale;
6155         oldwidth = r_refdef.view.width;
6156         oldheight = r_refdef.view.height;
6157         r_refdef.view.width = r_bloomstate.bloomwidth;
6158         r_refdef.view.height = r_bloomstate.bloomheight;
6159
6160         if(r_hdr.integer < 2)
6161                 r_waterstate.enabled = false;
6162
6163         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6164         // TODO: add exposure compensation features
6165         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6166
6167         r_refdef.view.showdebug = false;
6168         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6169
6170         R_ResetViewRendering3D();
6171
6172         R_ClearScreen(r_refdef.fogenabled);
6173         if (r_timereport_active)
6174                 R_TimeReport("HDRclear");
6175
6176         R_View_Update();
6177         if (r_timereport_active)
6178                 R_TimeReport("visibility");
6179
6180         // only do secondary renders with HDR if r_hdr is 2 or higher
6181         r_waterstate.numwaterplanes = 0;
6182         if (r_waterstate.enabled)
6183                 R_RenderWaterPlanes();
6184
6185         r_refdef.view.showdebug = true;
6186         R_RenderScene();
6187         r_waterstate.numwaterplanes = 0;
6188
6189         R_ResetViewRendering2D();
6190
6191         R_Bloom_CopyHDRTexture();
6192         R_Bloom_MakeTexture();
6193
6194         // restore the view settings
6195         r_waterstate.enabled = oldwaterstate;
6196         r_refdef.view.width = oldwidth;
6197         r_refdef.view.height = oldheight;
6198         r_refdef.view.colorscale = oldcolorscale;
6199
6200         R_ResetViewRendering3D();
6201
6202         R_ClearScreen(r_refdef.fogenabled);
6203         if (r_timereport_active)
6204                 R_TimeReport("viewclear");
6205 }
6206
6207 static void R_BlendView(void)
6208 {
6209         unsigned int permutation;
6210         float uservecs[4][4];
6211
6212         switch (vid.renderpath)
6213         {
6214         case RENDERPATH_GL20:
6215         case RENDERPATH_D3D9:
6216         case RENDERPATH_D3D10:
6217         case RENDERPATH_D3D11:
6218         case RENDERPATH_SOFT:
6219         case RENDERPATH_GLES2:
6220                 permutation =
6221                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6222                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6223                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6224                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6225                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6226
6227                 if (r_bloomstate.texture_screen)
6228                 {
6229                         // make sure the buffer is available
6230                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6231
6232                         R_ResetViewRendering2D();
6233                         R_Mesh_SetMainRenderTargets();
6234
6235                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6236                         {
6237                                 // declare variables
6238                                 float speed;
6239                                 static float avgspeed;
6240
6241                                 speed = VectorLength(cl.movement_velocity);
6242
6243                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6244                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6245
6246                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6247                                 speed = bound(0, speed, 1);
6248                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6249
6250                                 // calculate values into a standard alpha
6251                                 cl.motionbluralpha = 1 - exp(-
6252                                                 (
6253                                                  (r_motionblur.value * speed / 80)
6254                                                  +
6255                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6256                                                 )
6257                                                 /
6258                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6259                                            );
6260
6261                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6262                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6263                                 // apply the blur
6264                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6265                                 {
6266                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6267                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6268                                         switch(vid.renderpath)
6269                                         {
6270                                         case RENDERPATH_GL11:
6271                                         case RENDERPATH_GL13:
6272                                         case RENDERPATH_GL20:
6273                                         case RENDERPATH_GLES1:
6274                                         case RENDERPATH_GLES2:
6275                                         case RENDERPATH_SOFT:
6276                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6277                                                 break;
6278                                         case RENDERPATH_D3D9:
6279                                         case RENDERPATH_D3D10:
6280                                         case RENDERPATH_D3D11:
6281                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6282                                                 break;
6283                                         }
6284                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6285                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6286                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6287                                 }
6288                         }
6289
6290                         // copy view into the screen texture
6291                         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);
6292                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6293                 }
6294                 else if (!r_bloomstate.texture_bloom)
6295                 {
6296                         // we may still have to do view tint...
6297                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6298                         {
6299                                 // apply a color tint to the whole view
6300                                 R_ResetViewRendering2D();
6301                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6302                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6303                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6304                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6305                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6306                         }
6307                         break; // no screen processing, no bloom, skip it
6308                 }
6309
6310                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6311                 {
6312                         // render simple bloom effect
6313                         // copy the screen and shrink it and darken it for the bloom process
6314                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6315                         // make the bloom texture
6316                         R_Bloom_MakeTexture();
6317                 }
6318
6319 #if _MSC_VER >= 1400
6320 #define sscanf sscanf_s
6321 #endif
6322                 memset(uservecs, 0, sizeof(uservecs));
6323                 if (r_glsl_postprocess_uservec1_enable.integer)
6324                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6325                 if (r_glsl_postprocess_uservec2_enable.integer)
6326                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6327                 if (r_glsl_postprocess_uservec3_enable.integer)
6328                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6329                 if (r_glsl_postprocess_uservec4_enable.integer)
6330                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6331
6332                 R_ResetViewRendering2D();
6333                 GL_Color(1, 1, 1, 1);
6334                 GL_BlendFunc(GL_ONE, GL_ZERO);
6335
6336                 switch(vid.renderpath)
6337                 {
6338                 case RENDERPATH_GL20:
6339                 case RENDERPATH_GLES2:
6340                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6341                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6342                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6343                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6344                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6345                         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]);
6346                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6347                         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]);
6348                         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]);
6349                         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]);
6350                         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]);
6351                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6352                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6353                         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);
6354                         break;
6355                 case RENDERPATH_D3D9:
6356 #ifdef SUPPORTD3D
6357                         // 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...
6358                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6359                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6360                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6361                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6362                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6363                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6364                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6365                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6366                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6367                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6368                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6369                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6370                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6371                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6372 #endif
6373                         break;
6374                 case RENDERPATH_D3D10:
6375                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6376                         break;
6377                 case RENDERPATH_D3D11:
6378                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6379                         break;
6380                 case RENDERPATH_SOFT:
6381                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6382                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6383                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6384                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6385                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6386                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6387                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6388                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6389                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6390                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6391                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6392                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6393                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6394                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6395                         break;
6396                 default:
6397                         break;
6398                 }
6399                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6400                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6401                 break;
6402         case RENDERPATH_GL11:
6403         case RENDERPATH_GL13:
6404         case RENDERPATH_GLES1:
6405                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6406                 {
6407                         // apply a color tint to the whole view
6408                         R_ResetViewRendering2D();
6409                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6410                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6411                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6412                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6413                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6414                 }
6415                 break;
6416         }
6417 }
6418
6419 matrix4x4_t r_waterscrollmatrix;
6420
6421 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6422 {
6423         if (r_refdef.fog_density)
6424         {
6425                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6426                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6427                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6428
6429                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6430                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6431                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6432                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6433
6434                 {
6435                         vec3_t fogvec;
6436                         VectorCopy(r_refdef.fogcolor, fogvec);
6437                         //   color.rgb *= ContrastBoost * SceneBrightness;
6438                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6439                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6440                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6441                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6442                 }
6443         }
6444 }
6445
6446 void R_UpdateVariables(void)
6447 {
6448         R_Textures_Frame();
6449
6450         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6451
6452         r_refdef.farclip = r_farclip_base.value;
6453         if (r_refdef.scene.worldmodel)
6454                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6455         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6456
6457         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6458                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6459         r_refdef.polygonfactor = 0;
6460         r_refdef.polygonoffset = 0;
6461         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6462         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6463
6464         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6465         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6466         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6467         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6468         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6469         if (FAKELIGHT_ENABLED)
6470         {
6471                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6472         }
6473         if (r_showsurfaces.integer)
6474         {
6475                 r_refdef.scene.rtworld = false;
6476                 r_refdef.scene.rtworldshadows = false;
6477                 r_refdef.scene.rtdlight = false;
6478                 r_refdef.scene.rtdlightshadows = false;
6479                 r_refdef.lightmapintensity = 0;
6480         }
6481
6482         if (gamemode == GAME_NEHAHRA)
6483         {
6484                 if (gl_fogenable.integer)
6485                 {
6486                         r_refdef.oldgl_fogenable = true;
6487                         r_refdef.fog_density = gl_fogdensity.value;
6488                         r_refdef.fog_red = gl_fogred.value;
6489                         r_refdef.fog_green = gl_foggreen.value;
6490                         r_refdef.fog_blue = gl_fogblue.value;
6491                         r_refdef.fog_alpha = 1;
6492                         r_refdef.fog_start = 0;
6493                         r_refdef.fog_end = gl_skyclip.value;
6494                         r_refdef.fog_height = 1<<30;
6495                         r_refdef.fog_fadedepth = 128;
6496                 }
6497                 else if (r_refdef.oldgl_fogenable)
6498                 {
6499                         r_refdef.oldgl_fogenable = false;
6500                         r_refdef.fog_density = 0;
6501                         r_refdef.fog_red = 0;
6502                         r_refdef.fog_green = 0;
6503                         r_refdef.fog_blue = 0;
6504                         r_refdef.fog_alpha = 0;
6505                         r_refdef.fog_start = 0;
6506                         r_refdef.fog_end = 0;
6507                         r_refdef.fog_height = 1<<30;
6508                         r_refdef.fog_fadedepth = 128;
6509                 }
6510         }
6511
6512         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6513         r_refdef.fog_start = max(0, r_refdef.fog_start);
6514         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6515
6516         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6517
6518         if (r_refdef.fog_density && r_drawfog.integer)
6519         {
6520                 r_refdef.fogenabled = true;
6521                 // this is the point where the fog reaches 0.9986 alpha, which we
6522                 // consider a good enough cutoff point for the texture
6523                 // (0.9986 * 256 == 255.6)
6524                 if (r_fog_exp2.integer)
6525                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6526                 else
6527                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6528                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6529                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6530                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6531                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6532                         R_BuildFogHeightTexture();
6533                 // fog color was already set
6534                 // update the fog texture
6535                 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)
6536                         R_BuildFogTexture();
6537                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6538                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6539         }
6540         else
6541                 r_refdef.fogenabled = false;
6542
6543         switch(vid.renderpath)
6544         {
6545         case RENDERPATH_GL20:
6546         case RENDERPATH_D3D9:
6547         case RENDERPATH_D3D10:
6548         case RENDERPATH_D3D11:
6549         case RENDERPATH_SOFT:
6550         case RENDERPATH_GLES2:
6551                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6552                 {
6553                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6554                         {
6555                                 // build GLSL gamma texture
6556 #define RAMPWIDTH 256
6557                                 unsigned short ramp[RAMPWIDTH * 3];
6558                                 unsigned char rampbgr[RAMPWIDTH][4];
6559                                 int i;
6560
6561                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6562
6563                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6564                                 for(i = 0; i < RAMPWIDTH; ++i)
6565                                 {
6566                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6567                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6568                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6569                                         rampbgr[i][3] = 0;
6570                                 }
6571                                 if (r_texture_gammaramps)
6572                                 {
6573                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6574                                 }
6575                                 else
6576                                 {
6577                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6578                                 }
6579                         }
6580                 }
6581                 else
6582                 {
6583                         // remove GLSL gamma texture
6584                 }
6585                 break;
6586         case RENDERPATH_GL11:
6587         case RENDERPATH_GL13:
6588         case RENDERPATH_GLES1:
6589                 break;
6590         }
6591 }
6592
6593 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6594 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6595 /*
6596 ================
6597 R_SelectScene
6598 ================
6599 */
6600 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6601         if( scenetype != r_currentscenetype ) {
6602                 // store the old scenetype
6603                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6604                 r_currentscenetype = scenetype;
6605                 // move in the new scene
6606                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6607         }
6608 }
6609
6610 /*
6611 ================
6612 R_GetScenePointer
6613 ================
6614 */
6615 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6616 {
6617         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6618         if( scenetype == r_currentscenetype ) {
6619                 return &r_refdef.scene;
6620         } else {
6621                 return &r_scenes_store[ scenetype ];
6622         }
6623 }
6624
6625 /*
6626 ================
6627 R_RenderView
6628 ================
6629 */
6630 int dpsoftrast_test;
6631 void R_RenderView(void)
6632 {
6633         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6634
6635         dpsoftrast_test = r_test.integer;
6636
6637         if (r_timereport_active)
6638                 R_TimeReport("start");
6639         r_textureframe++; // used only by R_GetCurrentTexture
6640         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6641
6642         if(R_CompileShader_CheckStaticParms())
6643                 R_GLSL_Restart_f();
6644
6645         if (!r_drawentities.integer)
6646                 r_refdef.scene.numentities = 0;
6647
6648         R_AnimCache_ClearCache();
6649         R_FrameData_NewFrame();
6650
6651         /* adjust for stereo display */
6652         if(R_Stereo_Active())
6653         {
6654                 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);
6655                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6656         }
6657
6658         if (r_refdef.view.isoverlay)
6659         {
6660                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6661                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6662                 R_TimeReport("depthclear");
6663
6664                 r_refdef.view.showdebug = false;
6665
6666                 r_waterstate.enabled = false;
6667                 r_waterstate.numwaterplanes = 0;
6668
6669                 R_RenderScene();
6670
6671                 r_refdef.view.matrix = originalmatrix;
6672
6673                 CHECKGLERROR
6674                 return;
6675         }
6676
6677         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6678         {
6679                 r_refdef.view.matrix = originalmatrix;
6680                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6681         }
6682
6683         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6684
6685         R_RenderView_UpdateViewVectors();
6686
6687         R_Shadow_UpdateWorldLightSelection();
6688
6689         R_Bloom_StartFrame();
6690         R_Water_StartFrame();
6691
6692         CHECKGLERROR
6693         if (r_timereport_active)
6694                 R_TimeReport("viewsetup");
6695
6696         R_ResetViewRendering3D();
6697
6698         if (r_refdef.view.clear || r_refdef.fogenabled)
6699         {
6700                 R_ClearScreen(r_refdef.fogenabled);
6701                 if (r_timereport_active)
6702                         R_TimeReport("viewclear");
6703         }
6704         r_refdef.view.clear = true;
6705
6706         // this produces a bloom texture to be used in R_BlendView() later
6707         if (r_bloomstate.hdr)
6708         {
6709                 R_HDR_RenderBloomTexture();
6710                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6711                 r_textureframe++; // used only by R_GetCurrentTexture
6712         }
6713
6714         r_refdef.view.showdebug = true;
6715
6716         R_View_Update();
6717         if (r_timereport_active)
6718                 R_TimeReport("visibility");
6719
6720         r_waterstate.numwaterplanes = 0;
6721         if (r_waterstate.enabled)
6722                 R_RenderWaterPlanes();
6723
6724         R_RenderScene();
6725         r_waterstate.numwaterplanes = 0;
6726
6727         R_BlendView();
6728         if (r_timereport_active)
6729                 R_TimeReport("blendview");
6730
6731         GL_Scissor(0, 0, vid.width, vid.height);
6732         GL_ScissorTest(false);
6733
6734         r_refdef.view.matrix = originalmatrix;
6735
6736         CHECKGLERROR
6737 }
6738
6739 void R_RenderWaterPlanes(void)
6740 {
6741         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6742         {
6743                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6744                 if (r_timereport_active)
6745                         R_TimeReport("waterworld");
6746         }
6747
6748         // don't let sound skip if going slow
6749         if (r_refdef.scene.extraupdate)
6750                 S_ExtraUpdate ();
6751
6752         R_DrawModelsAddWaterPlanes();
6753         if (r_timereport_active)
6754                 R_TimeReport("watermodels");
6755
6756         if (r_waterstate.numwaterplanes)
6757         {
6758                 R_Water_ProcessPlanes();
6759                 if (r_timereport_active)
6760                         R_TimeReport("waterscenes");
6761         }
6762 }
6763
6764 extern void R_DrawLightningBeams (void);
6765 extern void VM_CL_AddPolygonsToMeshQueue (void);
6766 extern void R_DrawPortals (void);
6767 extern cvar_t cl_locs_show;
6768 static void R_DrawLocs(void);
6769 static void R_DrawEntityBBoxes(void);
6770 static void R_DrawModelDecals(void);
6771 extern void R_DrawModelShadows(void);
6772 extern void R_DrawModelShadowMaps(void);
6773 extern cvar_t cl_decals_newsystem;
6774 extern qboolean r_shadow_usingdeferredprepass;
6775 void R_RenderScene(void)
6776 {
6777         qboolean shadowmapping = false;
6778
6779         if (r_timereport_active)
6780                 R_TimeReport("beginscene");
6781
6782         r_refdef.stats.renders++;
6783
6784         R_UpdateFogColor();
6785
6786         // don't let sound skip if going slow
6787         if (r_refdef.scene.extraupdate)
6788                 S_ExtraUpdate ();
6789
6790         R_MeshQueue_BeginScene();
6791
6792         R_SkyStartFrame();
6793
6794         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);
6795
6796         if (r_timereport_active)
6797                 R_TimeReport("skystartframe");
6798
6799         if (cl.csqc_vidvars.drawworld)
6800         {
6801                 // don't let sound skip if going slow
6802                 if (r_refdef.scene.extraupdate)
6803                         S_ExtraUpdate ();
6804
6805                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6806                 {
6807                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6808                         if (r_timereport_active)
6809                                 R_TimeReport("worldsky");
6810                 }
6811
6812                 if (R_DrawBrushModelsSky() && r_timereport_active)
6813                         R_TimeReport("bmodelsky");
6814
6815                 if (skyrendermasked && skyrenderlater)
6816                 {
6817                         // we have to force off the water clipping plane while rendering sky
6818                         R_SetupView(false);
6819                         R_Sky();
6820                         R_SetupView(true);
6821                         if (r_timereport_active)
6822                                 R_TimeReport("sky");
6823                 }
6824         }
6825
6826         R_AnimCache_CacheVisibleEntities();
6827         if (r_timereport_active)
6828                 R_TimeReport("animation");
6829
6830         R_Shadow_PrepareLights();
6831         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6832                 R_Shadow_PrepareModelShadows();
6833         if (r_timereport_active)
6834                 R_TimeReport("preparelights");
6835
6836         if (R_Shadow_ShadowMappingEnabled())
6837                 shadowmapping = true;
6838
6839         if (r_shadow_usingdeferredprepass)
6840                 R_Shadow_DrawPrepass();
6841
6842         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6843         {
6844                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6845                 if (r_timereport_active)
6846                         R_TimeReport("worlddepth");
6847         }
6848         if (r_depthfirst.integer >= 2)
6849         {
6850                 R_DrawModelsDepth();
6851                 if (r_timereport_active)
6852                         R_TimeReport("modeldepth");
6853         }
6854
6855         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6856         {
6857                 R_DrawModelShadowMaps();
6858                 R_ResetViewRendering3D();
6859                 // don't let sound skip if going slow
6860                 if (r_refdef.scene.extraupdate)
6861                         S_ExtraUpdate ();
6862         }
6863
6864         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6865         {
6866                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6867                 if (r_timereport_active)
6868                         R_TimeReport("world");
6869         }
6870
6871         // don't let sound skip if going slow
6872         if (r_refdef.scene.extraupdate)
6873                 S_ExtraUpdate ();
6874
6875         R_DrawModels();
6876         if (r_timereport_active)
6877                 R_TimeReport("models");
6878
6879         // don't let sound skip if going slow
6880         if (r_refdef.scene.extraupdate)
6881                 S_ExtraUpdate ();
6882
6883         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6884         {
6885                 R_DrawModelShadows();
6886                 R_ResetViewRendering3D();
6887                 // don't let sound skip if going slow
6888                 if (r_refdef.scene.extraupdate)
6889                         S_ExtraUpdate ();
6890         }
6891
6892         if (!r_shadow_usingdeferredprepass)
6893         {
6894                 R_Shadow_DrawLights();
6895                 if (r_timereport_active)
6896                         R_TimeReport("rtlights");
6897         }
6898
6899         // don't let sound skip if going slow
6900         if (r_refdef.scene.extraupdate)
6901                 S_ExtraUpdate ();
6902
6903         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6904         {
6905                 R_DrawModelShadows();
6906                 R_ResetViewRendering3D();
6907                 // don't let sound skip if going slow
6908                 if (r_refdef.scene.extraupdate)
6909                         S_ExtraUpdate ();
6910         }
6911
6912         if (cl.csqc_vidvars.drawworld)
6913         {
6914                 if (cl_decals_newsystem.integer)
6915                 {
6916                         R_DrawModelDecals();
6917                         if (r_timereport_active)
6918                                 R_TimeReport("modeldecals");
6919                 }
6920                 else
6921                 {
6922                         R_DrawDecals();
6923                         if (r_timereport_active)
6924                                 R_TimeReport("decals");
6925                 }
6926
6927                 R_DrawParticles();
6928                 if (r_timereport_active)
6929                         R_TimeReport("particles");
6930
6931                 R_DrawExplosions();
6932                 if (r_timereport_active)
6933                         R_TimeReport("explosions");
6934
6935                 R_DrawLightningBeams();
6936                 if (r_timereport_active)
6937                         R_TimeReport("lightning");
6938         }
6939
6940         VM_CL_AddPolygonsToMeshQueue();
6941
6942         if (r_refdef.view.showdebug)
6943         {
6944                 if (cl_locs_show.integer)
6945                 {
6946                         R_DrawLocs();
6947                         if (r_timereport_active)
6948                                 R_TimeReport("showlocs");
6949                 }
6950
6951                 if (r_drawportals.integer)
6952                 {
6953                         R_DrawPortals();
6954                         if (r_timereport_active)
6955                                 R_TimeReport("portals");
6956                 }
6957
6958                 if (r_showbboxes.value > 0)
6959                 {
6960                         R_DrawEntityBBoxes();
6961                         if (r_timereport_active)
6962                                 R_TimeReport("bboxes");
6963                 }
6964         }
6965
6966         if (r_transparent.integer)
6967         {
6968                 R_MeshQueue_RenderTransparent();
6969                 if (r_timereport_active)
6970                         R_TimeReport("drawtrans");
6971         }
6972
6973         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))
6974         {
6975                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6976                 if (r_timereport_active)
6977                         R_TimeReport("worlddebug");
6978                 R_DrawModelsDebug();
6979                 if (r_timereport_active)
6980                         R_TimeReport("modeldebug");
6981         }
6982
6983         if (cl.csqc_vidvars.drawworld)
6984         {
6985                 R_Shadow_DrawCoronas();
6986                 if (r_timereport_active)
6987                         R_TimeReport("coronas");
6988         }
6989
6990 #if 0
6991         {
6992                 GL_DepthTest(false);
6993                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6994                 GL_Color(1, 1, 1, 1);
6995                 qglBegin(GL_POLYGON);
6996                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6997                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6998                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6999                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7000                 qglEnd();
7001                 qglBegin(GL_POLYGON);
7002                 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]);
7003                 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]);
7004                 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]);
7005                 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]);
7006                 qglEnd();
7007                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7008         }
7009 #endif
7010
7011         // don't let sound skip if going slow
7012         if (r_refdef.scene.extraupdate)
7013                 S_ExtraUpdate ();
7014
7015         R_ResetViewRendering2D();
7016 }
7017
7018 static const unsigned short bboxelements[36] =
7019 {
7020         5, 1, 3, 5, 3, 7,
7021         6, 2, 0, 6, 0, 4,
7022         7, 3, 2, 7, 2, 6,
7023         4, 0, 1, 4, 1, 5,
7024         4, 5, 7, 4, 7, 6,
7025         1, 0, 2, 1, 2, 3,
7026 };
7027
7028 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7029 {
7030         int i;
7031         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7032
7033         RSurf_ActiveWorldEntity();
7034
7035         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7036         GL_DepthMask(false);
7037         GL_DepthRange(0, 1);
7038         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7039 //      R_Mesh_ResetTextureState();
7040
7041         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7042         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7043         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7044         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7045         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7046         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7047         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7048         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7049         R_FillColors(color4f, 8, cr, cg, cb, ca);
7050         if (r_refdef.fogenabled)
7051         {
7052                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7053                 {
7054                         f1 = RSurf_FogVertex(v);
7055                         f2 = 1 - f1;
7056                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7057                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7058                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7059                 }
7060         }
7061         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7062         R_Mesh_ResetTextureState();
7063         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7064         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7065 }
7066
7067 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7068 {
7069         int i;
7070         float color[4];
7071         prvm_edict_t *edict;
7072         prvm_prog_t *prog_save = prog;
7073
7074         // this function draws bounding boxes of server entities
7075         if (!sv.active)
7076                 return;
7077
7078         GL_CullFace(GL_NONE);
7079         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7080
7081         prog = 0;
7082         SV_VM_Begin();
7083         for (i = 0;i < numsurfaces;i++)
7084         {
7085                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7086                 switch ((int)edict->fields.server->solid)
7087                 {
7088                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7089                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7090                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7091                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7092                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7093                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7094                 }
7095                 color[3] *= r_showbboxes.value;
7096                 color[3] = bound(0, color[3], 1);
7097                 GL_DepthTest(!r_showdisabledepthtest.integer);
7098                 GL_CullFace(r_refdef.view.cullface_front);
7099                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7100         }
7101         SV_VM_End();
7102         prog = prog_save;
7103 }
7104
7105 static void R_DrawEntityBBoxes(void)
7106 {
7107         int i;
7108         prvm_edict_t *edict;
7109         vec3_t center;
7110         prvm_prog_t *prog_save = prog;
7111
7112         // this function draws bounding boxes of server entities
7113         if (!sv.active)
7114                 return;
7115
7116         prog = 0;
7117         SV_VM_Begin();
7118         for (i = 0;i < prog->num_edicts;i++)
7119         {
7120                 edict = PRVM_EDICT_NUM(i);
7121                 if (edict->priv.server->free)
7122                         continue;
7123                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7124                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7125                         continue;
7126                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7127                         continue;
7128                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7129                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7130         }
7131         SV_VM_End();
7132         prog = prog_save;
7133 }
7134
7135 static const int nomodelelement3i[24] =
7136 {
7137         5, 2, 0,
7138         5, 1, 2,
7139         5, 0, 3,
7140         5, 3, 1,
7141         0, 2, 4,
7142         2, 1, 4,
7143         3, 0, 4,
7144         1, 3, 4
7145 };
7146
7147 static const unsigned short nomodelelement3s[24] =
7148 {
7149         5, 2, 0,
7150         5, 1, 2,
7151         5, 0, 3,
7152         5, 3, 1,
7153         0, 2, 4,
7154         2, 1, 4,
7155         3, 0, 4,
7156         1, 3, 4
7157 };
7158
7159 static const float nomodelvertex3f[6*3] =
7160 {
7161         -16,   0,   0,
7162          16,   0,   0,
7163           0, -16,   0,
7164           0,  16,   0,
7165           0,   0, -16,
7166           0,   0,  16
7167 };
7168
7169 static const float nomodelcolor4f[6*4] =
7170 {
7171         0.0f, 0.0f, 0.5f, 1.0f,
7172         0.0f, 0.0f, 0.5f, 1.0f,
7173         0.0f, 0.5f, 0.0f, 1.0f,
7174         0.0f, 0.5f, 0.0f, 1.0f,
7175         0.5f, 0.0f, 0.0f, 1.0f,
7176         0.5f, 0.0f, 0.0f, 1.0f
7177 };
7178
7179 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7180 {
7181         int i;
7182         float f1, f2, *c;
7183         float color4f[6*4];
7184
7185         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);
7186
7187         // this is only called once per entity so numsurfaces is always 1, and
7188         // surfacelist is always {0}, so this code does not handle batches
7189
7190         if (rsurface.ent_flags & RENDER_ADDITIVE)
7191         {
7192                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7193                 GL_DepthMask(false);
7194         }
7195         else if (rsurface.colormod[3] < 1)
7196         {
7197                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7198                 GL_DepthMask(false);
7199         }
7200         else
7201         {
7202                 GL_BlendFunc(GL_ONE, GL_ZERO);
7203                 GL_DepthMask(true);
7204         }
7205         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7206         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7207         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7208         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7209         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7210         for (i = 0, c = color4f;i < 6;i++, c += 4)
7211         {
7212                 c[0] *= rsurface.colormod[0];
7213                 c[1] *= rsurface.colormod[1];
7214                 c[2] *= rsurface.colormod[2];
7215                 c[3] *= rsurface.colormod[3];
7216         }
7217         if (r_refdef.fogenabled)
7218         {
7219                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7220                 {
7221                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7222                         f2 = 1 - f1;
7223                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7224                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7225                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7226                 }
7227         }
7228 //      R_Mesh_ResetTextureState();
7229         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7230         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7231         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7232 }
7233
7234 void R_DrawNoModel(entity_render_t *ent)
7235 {
7236         vec3_t org;
7237         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7238         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7239                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7240         else
7241                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7242 }
7243
7244 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7245 {
7246         vec3_t right1, right2, diff, normal;
7247
7248         VectorSubtract (org2, org1, normal);
7249
7250         // calculate 'right' vector for start
7251         VectorSubtract (r_refdef.view.origin, org1, diff);
7252         CrossProduct (normal, diff, right1);
7253         VectorNormalize (right1);
7254
7255         // calculate 'right' vector for end
7256         VectorSubtract (r_refdef.view.origin, org2, diff);
7257         CrossProduct (normal, diff, right2);
7258         VectorNormalize (right2);
7259
7260         vert[ 0] = org1[0] + width * right1[0];
7261         vert[ 1] = org1[1] + width * right1[1];
7262         vert[ 2] = org1[2] + width * right1[2];
7263         vert[ 3] = org1[0] - width * right1[0];
7264         vert[ 4] = org1[1] - width * right1[1];
7265         vert[ 5] = org1[2] - width * right1[2];
7266         vert[ 6] = org2[0] - width * right2[0];
7267         vert[ 7] = org2[1] - width * right2[1];
7268         vert[ 8] = org2[2] - width * right2[2];
7269         vert[ 9] = org2[0] + width * right2[0];
7270         vert[10] = org2[1] + width * right2[1];
7271         vert[11] = org2[2] + width * right2[2];
7272 }
7273
7274 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)
7275 {
7276         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7277         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7278         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7279         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7280         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7281         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7282         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7283         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7284         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7285         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7286         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7287         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7288 }
7289
7290 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7291 {
7292         int i;
7293         float *vertex3f;
7294         float v[3];
7295         VectorSet(v, x, y, z);
7296         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7297                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7298                         break;
7299         if (i == mesh->numvertices)
7300         {
7301                 if (mesh->numvertices < mesh->maxvertices)
7302                 {
7303                         VectorCopy(v, vertex3f);
7304                         mesh->numvertices++;
7305                 }
7306                 return mesh->numvertices;
7307         }
7308         else
7309                 return i;
7310 }
7311
7312 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7313 {
7314         int i;
7315         int *e, element[3];
7316         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7317         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7318         e = mesh->element3i + mesh->numtriangles * 3;
7319         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7320         {
7321                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7322                 if (mesh->numtriangles < mesh->maxtriangles)
7323                 {
7324                         *e++ = element[0];
7325                         *e++ = element[1];
7326                         *e++ = element[2];
7327                         mesh->numtriangles++;
7328                 }
7329                 element[1] = element[2];
7330         }
7331 }
7332
7333 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7334 {
7335         int i;
7336         int *e, element[3];
7337         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7338         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7339         e = mesh->element3i + mesh->numtriangles * 3;
7340         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7341         {
7342                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7343                 if (mesh->numtriangles < mesh->maxtriangles)
7344                 {
7345                         *e++ = element[0];
7346                         *e++ = element[1];
7347                         *e++ = element[2];
7348                         mesh->numtriangles++;
7349                 }
7350                 element[1] = element[2];
7351         }
7352 }
7353
7354 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7355 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7356 {
7357         int planenum, planenum2;
7358         int w;
7359         int tempnumpoints;
7360         mplane_t *plane, *plane2;
7361         double maxdist;
7362         double temppoints[2][256*3];
7363         // figure out how large a bounding box we need to properly compute this brush
7364         maxdist = 0;
7365         for (w = 0;w < numplanes;w++)
7366                 maxdist = max(maxdist, fabs(planes[w].dist));
7367         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7368         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7369         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7370         {
7371                 w = 0;
7372                 tempnumpoints = 4;
7373                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7374                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7375                 {
7376                         if (planenum2 == planenum)
7377                                 continue;
7378                         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);
7379                         w = !w;
7380                 }
7381                 if (tempnumpoints < 3)
7382                         continue;
7383                 // generate elements forming a triangle fan for this polygon
7384                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7385         }
7386 }
7387
7388 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)
7389 {
7390         texturelayer_t *layer;
7391         layer = t->currentlayers + t->currentnumlayers++;
7392         layer->type = type;
7393         layer->depthmask = depthmask;
7394         layer->blendfunc1 = blendfunc1;
7395         layer->blendfunc2 = blendfunc2;
7396         layer->texture = texture;
7397         layer->texmatrix = *matrix;
7398         layer->color[0] = r;
7399         layer->color[1] = g;
7400         layer->color[2] = b;
7401         layer->color[3] = a;
7402 }
7403
7404 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7405 {
7406         if(parms[0] == 0 && parms[1] == 0)
7407                 return false;
7408         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7409                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7410                         return false;
7411         return true;
7412 }
7413
7414 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7415 {
7416         double index, f;
7417         index = parms[2] + rsurface.shadertime * parms[3];
7418         index -= floor(index);
7419         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7420         {
7421         default:
7422         case Q3WAVEFUNC_NONE:
7423         case Q3WAVEFUNC_NOISE:
7424         case Q3WAVEFUNC_COUNT:
7425                 f = 0;
7426                 break;
7427         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7428         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7429         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7430         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7431         case Q3WAVEFUNC_TRIANGLE:
7432                 index *= 4;
7433                 f = index - floor(index);
7434                 if (index < 1)
7435                         f = f;
7436                 else if (index < 2)
7437                         f = 1 - f;
7438                 else if (index < 3)
7439                         f = -f;
7440                 else
7441                         f = -(1 - f);
7442                 break;
7443         }
7444         f = parms[0] + parms[1] * f;
7445         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7446                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7447         return (float) f;
7448 }
7449
7450 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7451 {
7452         int w, h, idx;
7453         double f;
7454         double offsetd[2];
7455         float tcmat[12];
7456         matrix4x4_t matrix, temp;
7457         switch(tcmod->tcmod)
7458         {
7459                 case Q3TCMOD_COUNT:
7460                 case Q3TCMOD_NONE:
7461                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7462                                 matrix = r_waterscrollmatrix;
7463                         else
7464                                 matrix = identitymatrix;
7465                         break;
7466                 case Q3TCMOD_ENTITYTRANSLATE:
7467                         // this is used in Q3 to allow the gamecode to control texcoord
7468                         // scrolling on the entity, which is not supported in darkplaces yet.
7469                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7470                         break;
7471                 case Q3TCMOD_ROTATE:
7472                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7473                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7474                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7475                         break;
7476                 case Q3TCMOD_SCALE:
7477                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7478                         break;
7479                 case Q3TCMOD_SCROLL:
7480                         // extra care is needed because of precision breakdown with large values of time
7481                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7482                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7483                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7484                         break;
7485                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7486                         w = (int) tcmod->parms[0];
7487                         h = (int) tcmod->parms[1];
7488                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7489                         f = f - floor(f);
7490                         idx = (int) floor(f * w * h);
7491                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7492                         break;
7493                 case Q3TCMOD_STRETCH:
7494                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7495                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7496                         break;
7497                 case Q3TCMOD_TRANSFORM:
7498                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7499                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7500                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7501                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7502                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7503                         break;
7504                 case Q3TCMOD_TURBULENT:
7505                         // this is handled in the RSurf_PrepareVertices function
7506                         matrix = identitymatrix;
7507                         break;
7508         }
7509         temp = *texmatrix;
7510         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7511 }
7512
7513 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7514 {
7515         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7516         char name[MAX_QPATH];
7517         skinframe_t *skinframe;
7518         unsigned char pixels[296*194];
7519         strlcpy(cache->name, skinname, sizeof(cache->name));
7520         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7521         if (developer_loading.integer)
7522                 Con_Printf("loading %s\n", name);
7523         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7524         if (!skinframe || !skinframe->base)
7525         {
7526                 unsigned char *f;
7527                 fs_offset_t filesize;
7528                 skinframe = NULL;
7529                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7530                 if (f)
7531                 {
7532                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7533                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7534                         Mem_Free(f);
7535                 }
7536         }
7537         cache->skinframe = skinframe;
7538 }
7539
7540 texture_t *R_GetCurrentTexture(texture_t *t)
7541 {
7542         int i;
7543         const entity_render_t *ent = rsurface.entity;
7544         dp_model_t *model = ent->model;
7545         q3shaderinfo_layer_tcmod_t *tcmod;
7546
7547         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7548                 return t->currentframe;
7549         t->update_lastrenderframe = r_textureframe;
7550         t->update_lastrenderentity = (void *)ent;
7551
7552         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7553                 t->camera_entity = ent->entitynumber;
7554         else
7555                 t->camera_entity = 0;
7556
7557         // switch to an alternate material if this is a q1bsp animated material
7558         {
7559                 texture_t *texture = t;
7560                 int s = rsurface.ent_skinnum;
7561                 if ((unsigned int)s >= (unsigned int)model->numskins)
7562                         s = 0;
7563                 if (model->skinscenes)
7564                 {
7565                         if (model->skinscenes[s].framecount > 1)
7566                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7567                         else
7568                                 s = model->skinscenes[s].firstframe;
7569                 }
7570                 if (s > 0)
7571                         t = t + s * model->num_surfaces;
7572                 if (t->animated)
7573                 {
7574                         // use an alternate animation if the entity's frame is not 0,
7575                         // and only if the texture has an alternate animation
7576                         if (rsurface.ent_alttextures && t->anim_total[1])
7577                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7578                         else
7579                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7580                 }
7581                 texture->currentframe = t;
7582         }
7583
7584         // update currentskinframe to be a qw skin or animation frame
7585         if (rsurface.ent_qwskin >= 0)
7586         {
7587                 i = rsurface.ent_qwskin;
7588                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7589                 {
7590                         r_qwskincache_size = cl.maxclients;
7591                         if (r_qwskincache)
7592                                 Mem_Free(r_qwskincache);
7593                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7594                 }
7595                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7596                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7597                 t->currentskinframe = r_qwskincache[i].skinframe;
7598                 if (t->currentskinframe == NULL)
7599                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7600         }
7601         else if (t->numskinframes >= 2)
7602                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7603         if (t->backgroundnumskinframes >= 2)
7604                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7605
7606         t->currentmaterialflags = t->basematerialflags;
7607         t->currentalpha = rsurface.colormod[3];
7608         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7609                 t->currentalpha *= r_wateralpha.value;
7610         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7611                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7612         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7613                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7614         if (!(rsurface.ent_flags & RENDER_LIGHT))
7615                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7616         else if (FAKELIGHT_ENABLED)
7617         {
7618                 // no modellight if using fakelight for the map
7619         }
7620         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7621         {
7622                 // pick a model lighting mode
7623                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7624                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7625                 else
7626                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7627         }
7628         if (rsurface.ent_flags & RENDER_ADDITIVE)
7629                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7630         else if (t->currentalpha < 1)
7631                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7632         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7633                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7634         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7635                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7636         if (t->backgroundnumskinframes)
7637                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7638         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7639         {
7640                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7641                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7642         }
7643         else
7644                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7645         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7646                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7647
7648         // there is no tcmod
7649         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7650         {
7651                 t->currenttexmatrix = r_waterscrollmatrix;
7652                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7653         }
7654         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7655         {
7656                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7657                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7658         }
7659
7660         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7661                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7662         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7663                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7664
7665         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7666         if (t->currentskinframe->qpixels)
7667                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7668         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7669         if (!t->basetexture)
7670                 t->basetexture = r_texture_notexture;
7671         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7672         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7673         t->nmaptexture = t->currentskinframe->nmap;
7674         if (!t->nmaptexture)
7675                 t->nmaptexture = r_texture_blanknormalmap;
7676         t->glosstexture = r_texture_black;
7677         t->glowtexture = t->currentskinframe->glow;
7678         t->fogtexture = t->currentskinframe->fog;
7679         t->reflectmasktexture = t->currentskinframe->reflect;
7680         if (t->backgroundnumskinframes)
7681         {
7682                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7683                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7684                 t->backgroundglosstexture = r_texture_black;
7685                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7686                 if (!t->backgroundnmaptexture)
7687                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7688         }
7689         else
7690         {
7691                 t->backgroundbasetexture = r_texture_white;
7692                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7693                 t->backgroundglosstexture = r_texture_black;
7694                 t->backgroundglowtexture = NULL;
7695         }
7696         t->specularpower = r_shadow_glossexponent.value;
7697         // TODO: store reference values for these in the texture?
7698         t->specularscale = 0;
7699         if (r_shadow_gloss.integer > 0)
7700         {
7701                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7702                 {
7703                         if (r_shadow_glossintensity.value > 0)
7704                         {
7705                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7706                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7707                                 t->specularscale = r_shadow_glossintensity.value;
7708                         }
7709                 }
7710                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7711                 {
7712                         t->glosstexture = r_texture_white;
7713                         t->backgroundglosstexture = r_texture_white;
7714                         t->specularscale = r_shadow_gloss2intensity.value;
7715                         t->specularpower = r_shadow_gloss2exponent.value;
7716                 }
7717         }
7718         t->specularscale *= t->specularscalemod;
7719         t->specularpower *= t->specularpowermod;
7720
7721         // lightmaps mode looks bad with dlights using actual texturing, so turn
7722         // off the colormap and glossmap, but leave the normalmap on as it still
7723         // accurately represents the shading involved
7724         if (gl_lightmaps.integer)
7725         {
7726                 t->basetexture = r_texture_grey128;
7727                 t->pantstexture = r_texture_black;
7728                 t->shirttexture = r_texture_black;
7729                 t->nmaptexture = r_texture_blanknormalmap;
7730                 t->glosstexture = r_texture_black;
7731                 t->glowtexture = NULL;
7732                 t->fogtexture = NULL;
7733                 t->reflectmasktexture = NULL;
7734                 t->backgroundbasetexture = NULL;
7735                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7736                 t->backgroundglosstexture = r_texture_black;
7737                 t->backgroundglowtexture = NULL;
7738                 t->specularscale = 0;
7739                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7740         }
7741
7742         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7743         VectorClear(t->dlightcolor);
7744         t->currentnumlayers = 0;
7745         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7746         {
7747                 int blendfunc1, blendfunc2;
7748                 qboolean depthmask;
7749                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7750                 {
7751                         blendfunc1 = GL_SRC_ALPHA;
7752                         blendfunc2 = GL_ONE;
7753                 }
7754                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7755                 {
7756                         blendfunc1 = GL_SRC_ALPHA;
7757                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7758                 }
7759                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7760                 {
7761                         blendfunc1 = t->customblendfunc[0];
7762                         blendfunc2 = t->customblendfunc[1];
7763                 }
7764                 else
7765                 {
7766                         blendfunc1 = GL_ONE;
7767                         blendfunc2 = GL_ZERO;
7768                 }
7769                 // don't colormod evilblend textures
7770                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7771                         VectorSet(t->lightmapcolor, 1, 1, 1);
7772                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7773                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7774                 {
7775                         // fullbright is not affected by r_refdef.lightmapintensity
7776                         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]);
7777                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7778                                 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]);
7779                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7780                                 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]);
7781                 }
7782                 else
7783                 {
7784                         vec3_t ambientcolor;
7785                         float colorscale;
7786                         // set the color tint used for lights affecting this surface
7787                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7788                         colorscale = 2;
7789                         // q3bsp has no lightmap updates, so the lightstylevalue that
7790                         // would normally be baked into the lightmap must be
7791                         // applied to the color
7792                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7793                         if (model->type == mod_brushq3)
7794                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7795                         colorscale *= r_refdef.lightmapintensity;
7796                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7797                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7798                         // basic lit geometry
7799                         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]);
7800                         // add pants/shirt if needed
7801                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7802                                 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]);
7803                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7804                                 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]);
7805                         // now add ambient passes if needed
7806                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7807                         {
7808                                 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]);
7809                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7810                                         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]);
7811                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7812                                         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]);
7813                         }
7814                 }
7815                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7816                         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]);
7817                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7818                 {
7819                         // if this is opaque use alpha blend which will darken the earlier
7820                         // passes cheaply.
7821                         //
7822                         // if this is an alpha blended material, all the earlier passes
7823                         // were darkened by fog already, so we only need to add the fog
7824                         // color ontop through the fog mask texture
7825                         //
7826                         // if this is an additive blended material, all the earlier passes
7827                         // were darkened by fog already, and we should not add fog color
7828                         // (because the background was not darkened, there is no fog color
7829                         // that was lost behind it).
7830                         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]);
7831                 }
7832         }
7833
7834         return t->currentframe;
7835 }
7836
7837 rsurfacestate_t rsurface;
7838
7839 void RSurf_ActiveWorldEntity(void)
7840 {
7841         dp_model_t *model = r_refdef.scene.worldmodel;
7842         //if (rsurface.entity == r_refdef.scene.worldentity)
7843         //      return;
7844         rsurface.entity = r_refdef.scene.worldentity;
7845         rsurface.skeleton = NULL;
7846         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7847         rsurface.ent_skinnum = 0;
7848         rsurface.ent_qwskin = -1;
7849         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7850         rsurface.shadertime = r_refdef.scene.time;
7851         rsurface.matrix = identitymatrix;
7852         rsurface.inversematrix = identitymatrix;
7853         rsurface.matrixscale = 1;
7854         rsurface.inversematrixscale = 1;
7855         R_EntityMatrix(&identitymatrix);
7856         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7857         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7858         rsurface.fograngerecip = r_refdef.fograngerecip;
7859         rsurface.fogheightfade = r_refdef.fogheightfade;
7860         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7861         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7862         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7863         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7864         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7865         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7866         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7867         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7868         rsurface.colormod[3] = 1;
7869         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);
7870         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7871         rsurface.frameblend[0].lerp = 1;
7872         rsurface.ent_alttextures = false;
7873         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7874         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7875         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7876         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7877         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7878         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7879         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7880         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7881         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7882         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7883         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7884         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7885         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7886         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7887         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7888         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7889         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7890         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7891         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7892         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7893         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7894         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7895         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7896         rsurface.modelelement3i = model->surfmesh.data_element3i;
7897         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7898         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7899         rsurface.modelelement3s = model->surfmesh.data_element3s;
7900         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7901         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7902         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7903         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7904         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7905         rsurface.modelsurfaces = model->data_surfaces;
7906         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7907         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7908         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7909         rsurface.modelgeneratedvertex = false;
7910         rsurface.batchgeneratedvertex = false;
7911         rsurface.batchfirstvertex = 0;
7912         rsurface.batchnumvertices = 0;
7913         rsurface.batchfirsttriangle = 0;
7914         rsurface.batchnumtriangles = 0;
7915         rsurface.batchvertex3f  = NULL;
7916         rsurface.batchvertex3f_vertexbuffer = NULL;
7917         rsurface.batchvertex3f_bufferoffset = 0;
7918         rsurface.batchsvector3f = NULL;
7919         rsurface.batchsvector3f_vertexbuffer = NULL;
7920         rsurface.batchsvector3f_bufferoffset = 0;
7921         rsurface.batchtvector3f = NULL;
7922         rsurface.batchtvector3f_vertexbuffer = NULL;
7923         rsurface.batchtvector3f_bufferoffset = 0;
7924         rsurface.batchnormal3f  = NULL;
7925         rsurface.batchnormal3f_vertexbuffer = NULL;
7926         rsurface.batchnormal3f_bufferoffset = 0;
7927         rsurface.batchlightmapcolor4f = NULL;
7928         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7929         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7930         rsurface.batchtexcoordtexture2f = NULL;
7931         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7932         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7933         rsurface.batchtexcoordlightmap2f = NULL;
7934         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7935         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7936         rsurface.batchvertexmesh = NULL;
7937         rsurface.batchvertexmeshbuffer = NULL;
7938         rsurface.batchvertex3fbuffer = NULL;
7939         rsurface.batchelement3i = NULL;
7940         rsurface.batchelement3i_indexbuffer = NULL;
7941         rsurface.batchelement3i_bufferoffset = 0;
7942         rsurface.batchelement3s = NULL;
7943         rsurface.batchelement3s_indexbuffer = NULL;
7944         rsurface.batchelement3s_bufferoffset = 0;
7945         rsurface.passcolor4f = NULL;
7946         rsurface.passcolor4f_vertexbuffer = NULL;
7947         rsurface.passcolor4f_bufferoffset = 0;
7948 }
7949
7950 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7951 {
7952         dp_model_t *model = ent->model;
7953         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7954         //      return;
7955         rsurface.entity = (entity_render_t *)ent;
7956         rsurface.skeleton = ent->skeleton;
7957         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7958         rsurface.ent_skinnum = ent->skinnum;
7959         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;
7960         rsurface.ent_flags = ent->flags;
7961         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7962         rsurface.matrix = ent->matrix;
7963         rsurface.inversematrix = ent->inversematrix;
7964         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7965         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7966         R_EntityMatrix(&rsurface.matrix);
7967         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7968         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7969         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7970         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7971         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7972         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7973         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7974         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7975         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7976         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7977         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7978         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7979         rsurface.colormod[3] = ent->alpha;
7980         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7981         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7982         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7983         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7984         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7985         if (ent->model->brush.submodel && !prepass)
7986         {
7987                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7988                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7989         }
7990         if (model->surfmesh.isanimated && model->AnimateVertices)
7991         {
7992                 if (ent->animcache_vertex3f)
7993                 {
7994                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7995                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7996                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7997                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7998                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7999                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8000                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8001                 }
8002                 else if (wanttangents)
8003                 {
8004                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8005                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8006                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8007                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8008                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8009                         rsurface.modelvertexmesh = NULL;
8010                         rsurface.modelvertexmeshbuffer = NULL;
8011                         rsurface.modelvertex3fbuffer = NULL;
8012                 }
8013                 else if (wantnormals)
8014                 {
8015                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8016                         rsurface.modelsvector3f = NULL;
8017                         rsurface.modeltvector3f = NULL;
8018                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8019                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8020                         rsurface.modelvertexmesh = NULL;
8021                         rsurface.modelvertexmeshbuffer = NULL;
8022                         rsurface.modelvertex3fbuffer = NULL;
8023                 }
8024                 else
8025                 {
8026                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8027                         rsurface.modelsvector3f = NULL;
8028                         rsurface.modeltvector3f = NULL;
8029                         rsurface.modelnormal3f = NULL;
8030                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8031                         rsurface.modelvertexmesh = NULL;
8032                         rsurface.modelvertexmeshbuffer = NULL;
8033                         rsurface.modelvertex3fbuffer = NULL;
8034                 }
8035                 rsurface.modelvertex3f_vertexbuffer = 0;
8036                 rsurface.modelvertex3f_bufferoffset = 0;
8037                 rsurface.modelsvector3f_vertexbuffer = 0;
8038                 rsurface.modelsvector3f_bufferoffset = 0;
8039                 rsurface.modeltvector3f_vertexbuffer = 0;
8040                 rsurface.modeltvector3f_bufferoffset = 0;
8041                 rsurface.modelnormal3f_vertexbuffer = 0;
8042                 rsurface.modelnormal3f_bufferoffset = 0;
8043                 rsurface.modelgeneratedvertex = true;
8044         }
8045         else
8046         {
8047                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8048                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8050                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8051                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8053                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8054                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8056                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8057                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8058                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8059                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8060                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8061                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8062                 rsurface.modelgeneratedvertex = false;
8063         }
8064         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8065         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8067         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8068         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8070         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8071         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8073         rsurface.modelelement3i = model->surfmesh.data_element3i;
8074         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8075         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8076         rsurface.modelelement3s = model->surfmesh.data_element3s;
8077         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8078         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8079         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8080         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8081         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8082         rsurface.modelsurfaces = model->data_surfaces;
8083         rsurface.batchgeneratedvertex = false;
8084         rsurface.batchfirstvertex = 0;
8085         rsurface.batchnumvertices = 0;
8086         rsurface.batchfirsttriangle = 0;
8087         rsurface.batchnumtriangles = 0;
8088         rsurface.batchvertex3f  = NULL;
8089         rsurface.batchvertex3f_vertexbuffer = NULL;
8090         rsurface.batchvertex3f_bufferoffset = 0;
8091         rsurface.batchsvector3f = NULL;
8092         rsurface.batchsvector3f_vertexbuffer = NULL;
8093         rsurface.batchsvector3f_bufferoffset = 0;
8094         rsurface.batchtvector3f = NULL;
8095         rsurface.batchtvector3f_vertexbuffer = NULL;
8096         rsurface.batchtvector3f_bufferoffset = 0;
8097         rsurface.batchnormal3f  = NULL;
8098         rsurface.batchnormal3f_vertexbuffer = NULL;
8099         rsurface.batchnormal3f_bufferoffset = 0;
8100         rsurface.batchlightmapcolor4f = NULL;
8101         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8102         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8103         rsurface.batchtexcoordtexture2f = NULL;
8104         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8105         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8106         rsurface.batchtexcoordlightmap2f = NULL;
8107         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8108         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8109         rsurface.batchvertexmesh = NULL;
8110         rsurface.batchvertexmeshbuffer = NULL;
8111         rsurface.batchvertex3fbuffer = NULL;
8112         rsurface.batchelement3i = NULL;
8113         rsurface.batchelement3i_indexbuffer = NULL;
8114         rsurface.batchelement3i_bufferoffset = 0;
8115         rsurface.batchelement3s = NULL;
8116         rsurface.batchelement3s_indexbuffer = NULL;
8117         rsurface.batchelement3s_bufferoffset = 0;
8118         rsurface.passcolor4f = NULL;
8119         rsurface.passcolor4f_vertexbuffer = NULL;
8120         rsurface.passcolor4f_bufferoffset = 0;
8121 }
8122
8123 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)
8124 {
8125         rsurface.entity = r_refdef.scene.worldentity;
8126         rsurface.skeleton = NULL;
8127         rsurface.ent_skinnum = 0;
8128         rsurface.ent_qwskin = -1;
8129         rsurface.ent_flags = entflags;
8130         rsurface.shadertime = r_refdef.scene.time - shadertime;
8131         rsurface.modelnumvertices = numvertices;
8132         rsurface.modelnumtriangles = numtriangles;
8133         rsurface.matrix = *matrix;
8134         rsurface.inversematrix = *inversematrix;
8135         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8136         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8137         R_EntityMatrix(&rsurface.matrix);
8138         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8139         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8140         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8141         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8142         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8143         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8144         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8145         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8146         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8147         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8148         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8149         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8150         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);
8151         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8152         rsurface.frameblend[0].lerp = 1;
8153         rsurface.ent_alttextures = false;
8154         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8155         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8156         if (wanttangents)
8157         {
8158                 rsurface.modelvertex3f = (float *)vertex3f;
8159                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8160                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8161                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8162         }
8163         else if (wantnormals)
8164         {
8165                 rsurface.modelvertex3f = (float *)vertex3f;
8166                 rsurface.modelsvector3f = NULL;
8167                 rsurface.modeltvector3f = NULL;
8168                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8169         }
8170         else
8171         {
8172                 rsurface.modelvertex3f = (float *)vertex3f;
8173                 rsurface.modelsvector3f = NULL;
8174                 rsurface.modeltvector3f = NULL;
8175                 rsurface.modelnormal3f = NULL;
8176         }
8177         rsurface.modelvertexmesh = NULL;
8178         rsurface.modelvertexmeshbuffer = NULL;
8179         rsurface.modelvertex3fbuffer = NULL;
8180         rsurface.modelvertex3f_vertexbuffer = 0;
8181         rsurface.modelvertex3f_bufferoffset = 0;
8182         rsurface.modelsvector3f_vertexbuffer = 0;
8183         rsurface.modelsvector3f_bufferoffset = 0;
8184         rsurface.modeltvector3f_vertexbuffer = 0;
8185         rsurface.modeltvector3f_bufferoffset = 0;
8186         rsurface.modelnormal3f_vertexbuffer = 0;
8187         rsurface.modelnormal3f_bufferoffset = 0;
8188         rsurface.modelgeneratedvertex = true;
8189         rsurface.modellightmapcolor4f  = (float *)color4f;
8190         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8191         rsurface.modellightmapcolor4f_bufferoffset = 0;
8192         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8193         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8194         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8195         rsurface.modeltexcoordlightmap2f  = NULL;
8196         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8197         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8198         rsurface.modelelement3i = (int *)element3i;
8199         rsurface.modelelement3i_indexbuffer = NULL;
8200         rsurface.modelelement3i_bufferoffset = 0;
8201         rsurface.modelelement3s = (unsigned short *)element3s;
8202         rsurface.modelelement3s_indexbuffer = NULL;
8203         rsurface.modelelement3s_bufferoffset = 0;
8204         rsurface.modellightmapoffsets = NULL;
8205         rsurface.modelsurfaces = NULL;
8206         rsurface.batchgeneratedvertex = false;
8207         rsurface.batchfirstvertex = 0;
8208         rsurface.batchnumvertices = 0;
8209         rsurface.batchfirsttriangle = 0;
8210         rsurface.batchnumtriangles = 0;
8211         rsurface.batchvertex3f  = NULL;
8212         rsurface.batchvertex3f_vertexbuffer = NULL;
8213         rsurface.batchvertex3f_bufferoffset = 0;
8214         rsurface.batchsvector3f = NULL;
8215         rsurface.batchsvector3f_vertexbuffer = NULL;
8216         rsurface.batchsvector3f_bufferoffset = 0;
8217         rsurface.batchtvector3f = NULL;
8218         rsurface.batchtvector3f_vertexbuffer = NULL;
8219         rsurface.batchtvector3f_bufferoffset = 0;
8220         rsurface.batchnormal3f  = NULL;
8221         rsurface.batchnormal3f_vertexbuffer = NULL;
8222         rsurface.batchnormal3f_bufferoffset = 0;
8223         rsurface.batchlightmapcolor4f = NULL;
8224         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8225         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8226         rsurface.batchtexcoordtexture2f = NULL;
8227         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8228         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8229         rsurface.batchtexcoordlightmap2f = NULL;
8230         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8231         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8232         rsurface.batchvertexmesh = NULL;
8233         rsurface.batchvertexmeshbuffer = NULL;
8234         rsurface.batchvertex3fbuffer = NULL;
8235         rsurface.batchelement3i = NULL;
8236         rsurface.batchelement3i_indexbuffer = NULL;
8237         rsurface.batchelement3i_bufferoffset = 0;
8238         rsurface.batchelement3s = NULL;
8239         rsurface.batchelement3s_indexbuffer = NULL;
8240         rsurface.batchelement3s_bufferoffset = 0;
8241         rsurface.passcolor4f = NULL;
8242         rsurface.passcolor4f_vertexbuffer = NULL;
8243         rsurface.passcolor4f_bufferoffset = 0;
8244
8245         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8246         {
8247                 if ((wantnormals || wanttangents) && !normal3f)
8248                 {
8249                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8250                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8251                 }
8252                 if (wanttangents && !svector3f)
8253                 {
8254                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8255                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8256                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8257                 }
8258         }
8259 }
8260
8261 float RSurf_FogPoint(const float *v)
8262 {
8263         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8264         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8265         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8266         float FogHeightFade = r_refdef.fogheightfade;
8267         float fogfrac;
8268         unsigned int fogmasktableindex;
8269         if (r_refdef.fogplaneviewabove)
8270                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8271         else
8272                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8273         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8274         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8275 }
8276
8277 float RSurf_FogVertex(const float *v)
8278 {
8279         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8280         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8281         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8282         float FogHeightFade = rsurface.fogheightfade;
8283         float fogfrac;
8284         unsigned int fogmasktableindex;
8285         if (r_refdef.fogplaneviewabove)
8286                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8287         else
8288                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8289         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8290         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8291 }
8292
8293 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8294 {
8295         int i;
8296         for (i = 0;i < numelements;i++)
8297                 outelement3i[i] = inelement3i[i] + adjust;
8298 }
8299
8300 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8301 extern cvar_t gl_vbo;
8302 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8303 {
8304         int deformindex;
8305         int firsttriangle;
8306         int numtriangles;
8307         int firstvertex;
8308         int endvertex;
8309         int numvertices;
8310         int surfacefirsttriangle;
8311         int surfacenumtriangles;
8312         int surfacefirstvertex;
8313         int surfaceendvertex;
8314         int surfacenumvertices;
8315         int batchnumvertices;
8316         int batchnumtriangles;
8317         int needsupdate;
8318         int i, j;
8319         qboolean gaps;
8320         qboolean dynamicvertex;
8321         float amplitude;
8322         float animpos;
8323         float scale;
8324         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8325         float waveparms[4];
8326         q3shaderinfo_deform_t *deform;
8327         const msurface_t *surface, *firstsurface;
8328         r_vertexmesh_t *vertexmesh;
8329         if (!texturenumsurfaces)
8330                 return;
8331         // find vertex range of this surface batch
8332         gaps = false;
8333         firstsurface = texturesurfacelist[0];
8334         firsttriangle = firstsurface->num_firsttriangle;
8335         batchnumvertices = 0;
8336         batchnumtriangles = 0;
8337         firstvertex = endvertex = firstsurface->num_firstvertex;
8338         for (i = 0;i < texturenumsurfaces;i++)
8339         {
8340                 surface = texturesurfacelist[i];
8341                 if (surface != firstsurface + i)
8342                         gaps = true;
8343                 surfacefirstvertex = surface->num_firstvertex;
8344                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8345                 surfacenumvertices = surface->num_vertices;
8346                 surfacenumtriangles = surface->num_triangles;
8347                 if (firstvertex > surfacefirstvertex)
8348                         firstvertex = surfacefirstvertex;
8349                 if (endvertex < surfaceendvertex)
8350                         endvertex = surfaceendvertex;
8351                 batchnumvertices += surfacenumvertices;
8352                 batchnumtriangles += surfacenumtriangles;
8353         }
8354
8355         // we now know the vertex range used, and if there are any gaps in it
8356         rsurface.batchfirstvertex = firstvertex;
8357         rsurface.batchnumvertices = endvertex - firstvertex;
8358         rsurface.batchfirsttriangle = firsttriangle;
8359         rsurface.batchnumtriangles = batchnumtriangles;
8360
8361         // this variable holds flags for which properties have been updated that
8362         // may require regenerating vertexmesh array...
8363         needsupdate = 0;
8364
8365         // check if any dynamic vertex processing must occur
8366         dynamicvertex = false;
8367
8368         // if there is a chance of animated vertex colors, it's a dynamic batch
8369         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8370         {
8371                 dynamicvertex = true;
8372                 batchneed |= BATCHNEED_NOGAPS;
8373                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8374         }
8375
8376         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8377         {
8378                 switch (deform->deform)
8379                 {
8380                 default:
8381                 case Q3DEFORM_PROJECTIONSHADOW:
8382                 case Q3DEFORM_TEXT0:
8383                 case Q3DEFORM_TEXT1:
8384                 case Q3DEFORM_TEXT2:
8385                 case Q3DEFORM_TEXT3:
8386                 case Q3DEFORM_TEXT4:
8387                 case Q3DEFORM_TEXT5:
8388                 case Q3DEFORM_TEXT6:
8389                 case Q3DEFORM_TEXT7:
8390                 case Q3DEFORM_NONE:
8391                         break;
8392                 case Q3DEFORM_AUTOSPRITE:
8393                         dynamicvertex = true;
8394                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8395                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8396                         break;
8397                 case Q3DEFORM_AUTOSPRITE2:
8398                         dynamicvertex = true;
8399                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8400                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8401                         break;
8402                 case Q3DEFORM_NORMAL:
8403                         dynamicvertex = true;
8404                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8405                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8406                         break;
8407                 case Q3DEFORM_WAVE:
8408                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8409                                 break; // if wavefunc is a nop, ignore this transform
8410                         dynamicvertex = true;
8411                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8412                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8413                         break;
8414                 case Q3DEFORM_BULGE:
8415                         dynamicvertex = true;
8416                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8417                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8418                         break;
8419                 case Q3DEFORM_MOVE:
8420                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8421                                 break; // if wavefunc is a nop, ignore this transform
8422                         dynamicvertex = true;
8423                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8424                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8425                         break;
8426                 }
8427         }
8428         switch(rsurface.texture->tcgen.tcgen)
8429         {
8430         default:
8431         case Q3TCGEN_TEXTURE:
8432                 break;
8433         case Q3TCGEN_LIGHTMAP:
8434                 dynamicvertex = true;
8435                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8436                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8437                 break;
8438         case Q3TCGEN_VECTOR:
8439                 dynamicvertex = true;
8440                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8441                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8442                 break;
8443         case Q3TCGEN_ENVIRONMENT:
8444                 dynamicvertex = true;
8445                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8446                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8447                 break;
8448         }
8449         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8450         {
8451                 dynamicvertex = true;
8452                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8453                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8454         }
8455
8456         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8457         {
8458                 dynamicvertex = true;
8459                 batchneed |= BATCHNEED_NOGAPS;
8460                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8461         }
8462
8463         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8464         {
8465                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8466                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8467                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8468                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8469                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8470                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8471                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8472         }
8473
8474         // when the model data has no vertex buffer (dynamic mesh), we need to
8475         // eliminate gaps
8476         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8477                 batchneed |= BATCHNEED_NOGAPS;
8478
8479         // if needsupdate, we have to do a dynamic vertex batch for sure
8480         if (needsupdate & batchneed)
8481                 dynamicvertex = true;
8482
8483         // see if we need to build vertexmesh from arrays
8484         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8485                 dynamicvertex = true;
8486
8487         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8488         // also some drivers strongly dislike firstvertex
8489         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8490                 dynamicvertex = true;
8491
8492         rsurface.batchvertex3f = rsurface.modelvertex3f;
8493         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8494         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8495         rsurface.batchsvector3f = rsurface.modelsvector3f;
8496         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8497         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8498         rsurface.batchtvector3f = rsurface.modeltvector3f;
8499         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8500         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8501         rsurface.batchnormal3f = rsurface.modelnormal3f;
8502         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8503         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8504         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8505         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8506         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8507         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8508         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8509         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8510         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8511         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8512         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8513         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8514         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8515         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8516         rsurface.batchelement3i = rsurface.modelelement3i;
8517         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8518         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8519         rsurface.batchelement3s = rsurface.modelelement3s;
8520         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8521         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8522
8523         // if any dynamic vertex processing has to occur in software, we copy the
8524         // entire surface list together before processing to rebase the vertices
8525         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8526         //
8527         // if any gaps exist and we do not have a static vertex buffer, we have to
8528         // copy the surface list together to avoid wasting upload bandwidth on the
8529         // vertices in the gaps.
8530         //
8531         // if gaps exist and we have a static vertex buffer, we still have to
8532         // combine the index buffer ranges into one dynamic index buffer.
8533         //
8534         // in all cases we end up with data that can be drawn in one call.
8535
8536         if (!dynamicvertex)
8537         {
8538                 // static vertex data, just set pointers...
8539                 rsurface.batchgeneratedvertex = false;
8540                 // if there are gaps, we want to build a combined index buffer,
8541                 // otherwise use the original static buffer with an appropriate offset
8542                 if (gaps)
8543                 {
8544                         // build a new triangle elements array for this batch
8545                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8546                         rsurface.batchfirsttriangle = 0;
8547                         numtriangles = 0;
8548                         for (i = 0;i < texturenumsurfaces;i++)
8549                         {
8550                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8551                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8552                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8553                                 numtriangles += surfacenumtriangles;
8554                         }
8555                         rsurface.batchelement3i_indexbuffer = NULL;
8556                         rsurface.batchelement3i_bufferoffset = 0;
8557                         rsurface.batchelement3s = NULL;
8558                         rsurface.batchelement3s_indexbuffer = NULL;
8559                         rsurface.batchelement3s_bufferoffset = 0;
8560                         if (endvertex <= 65536)
8561                         {
8562                                 // make a 16bit (unsigned short) index array if possible
8563                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8564                                 for (i = 0;i < numtriangles*3;i++)
8565                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8566                         }
8567                 }
8568                 return;
8569         }
8570
8571         // something needs software processing, do it for real...
8572         // we only directly handle separate array data in this case and then
8573         // generate interleaved data if needed...
8574         rsurface.batchgeneratedvertex = true;
8575
8576         // now copy the vertex data into a combined array and make an index array
8577         // (this is what Quake3 does all the time)
8578         //if (gaps || rsurface.batchfirstvertex)
8579         {
8580                 rsurface.batchvertex3fbuffer = NULL;
8581                 rsurface.batchvertexmesh = NULL;
8582                 rsurface.batchvertexmeshbuffer = NULL;
8583                 rsurface.batchvertex3f = NULL;
8584                 rsurface.batchvertex3f_vertexbuffer = NULL;
8585                 rsurface.batchvertex3f_bufferoffset = 0;
8586                 rsurface.batchsvector3f = NULL;
8587                 rsurface.batchsvector3f_vertexbuffer = NULL;
8588                 rsurface.batchsvector3f_bufferoffset = 0;
8589                 rsurface.batchtvector3f = NULL;
8590                 rsurface.batchtvector3f_vertexbuffer = NULL;
8591                 rsurface.batchtvector3f_bufferoffset = 0;
8592                 rsurface.batchnormal3f = NULL;
8593                 rsurface.batchnormal3f_vertexbuffer = NULL;
8594                 rsurface.batchnormal3f_bufferoffset = 0;
8595                 rsurface.batchlightmapcolor4f = NULL;
8596                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8597                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8598                 rsurface.batchtexcoordtexture2f = NULL;
8599                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8600                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8601                 rsurface.batchtexcoordlightmap2f = NULL;
8602                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8603                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8604                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8605                 rsurface.batchelement3i_indexbuffer = NULL;
8606                 rsurface.batchelement3i_bufferoffset = 0;
8607                 rsurface.batchelement3s = NULL;
8608                 rsurface.batchelement3s_indexbuffer = NULL;
8609                 rsurface.batchelement3s_bufferoffset = 0;
8610                 // we'll only be setting up certain arrays as needed
8611                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8612                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8613                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8614                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8616                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8617                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8618                 {
8619                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8620                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8621                 }
8622                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8623                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8624                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8625                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8626                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8627                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8628                 numvertices = 0;
8629                 numtriangles = 0;
8630                 for (i = 0;i < texturenumsurfaces;i++)
8631                 {
8632                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8633                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8634                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8635                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8636                         // copy only the data requested
8637                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8638                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8639                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8640                         {
8641                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8642                                 {
8643                                         if (rsurface.batchvertex3f)
8644                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8645                                         else
8646                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8647                                 }
8648                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8649                                 {
8650                                         if (rsurface.modelnormal3f)
8651                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8652                                         else
8653                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8654                                 }
8655                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8656                                 {
8657                                         if (rsurface.modelsvector3f)
8658                                         {
8659                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8660                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8661                                         }
8662                                         else
8663                                         {
8664                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8665                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8666                                         }
8667                                 }
8668                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8669                                 {
8670                                         if (rsurface.modellightmapcolor4f)
8671                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8672                                         else
8673                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8674                                 }
8675                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8676                                 {
8677                                         if (rsurface.modeltexcoordtexture2f)
8678                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8679                                         else
8680                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8681                                 }
8682                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8683                                 {
8684                                         if (rsurface.modeltexcoordlightmap2f)
8685                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8686                                         else
8687                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8688                                 }
8689                         }
8690                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8691                         numvertices += surfacenumvertices;
8692                         numtriangles += surfacenumtriangles;
8693                 }
8694
8695                 // generate a 16bit index array as well if possible
8696                 // (in general, dynamic batches fit)
8697                 if (numvertices <= 65536)
8698                 {
8699                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8700                         for (i = 0;i < numtriangles*3;i++)
8701                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8702                 }
8703
8704                 // since we've copied everything, the batch now starts at 0
8705                 rsurface.batchfirstvertex = 0;
8706                 rsurface.batchnumvertices = batchnumvertices;
8707                 rsurface.batchfirsttriangle = 0;
8708                 rsurface.batchnumtriangles = batchnumtriangles;
8709         }
8710
8711         // q1bsp surfaces rendered in vertex color mode have to have colors
8712         // calculated based on lightstyles
8713         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8714         {
8715                 // generate color arrays for the surfaces in this list
8716                 int c[4];
8717                 int scale;
8718                 int size3;
8719                 const int *offsets;
8720                 const unsigned char *lm;
8721                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8722                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8723                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8724                 numvertices = 0;
8725                 for (i = 0;i < texturenumsurfaces;i++)
8726                 {
8727                         surface = texturesurfacelist[i];
8728                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8729                         surfacenumvertices = surface->num_vertices;
8730                         if (surface->lightmapinfo->samples)
8731                         {
8732                                 for (j = 0;j < surfacenumvertices;j++)
8733                                 {
8734                                         lm = surface->lightmapinfo->samples + offsets[j];
8735                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8736                                         VectorScale(lm, scale, c);
8737                                         if (surface->lightmapinfo->styles[1] != 255)
8738                                         {
8739                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8740                                                 lm += size3;
8741                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8742                                                 VectorMA(c, scale, lm, c);
8743                                                 if (surface->lightmapinfo->styles[2] != 255)
8744                                                 {
8745                                                         lm += size3;
8746                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8747                                                         VectorMA(c, scale, lm, c);
8748                                                         if (surface->lightmapinfo->styles[3] != 255)
8749                                                         {
8750                                                                 lm += size3;
8751                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8752                                                                 VectorMA(c, scale, lm, c);
8753                                                         }
8754                                                 }
8755                                         }
8756                                         c[0] >>= 7;
8757                                         c[1] >>= 7;
8758                                         c[2] >>= 7;
8759                                         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);
8760                                         numvertices++;
8761                                 }
8762                         }
8763                         else
8764                         {
8765                                 for (j = 0;j < surfacenumvertices;j++)
8766                                 {
8767                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8768                                         numvertices++;
8769                                 }
8770                         }
8771                 }
8772         }
8773
8774         // if vertices are deformed (sprite flares and things in maps, possibly
8775         // water waves, bulges and other deformations), modify the copied vertices
8776         // in place
8777         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8778         {
8779                 switch (deform->deform)
8780                 {
8781                 default:
8782                 case Q3DEFORM_PROJECTIONSHADOW:
8783                 case Q3DEFORM_TEXT0:
8784                 case Q3DEFORM_TEXT1:
8785                 case Q3DEFORM_TEXT2:
8786                 case Q3DEFORM_TEXT3:
8787                 case Q3DEFORM_TEXT4:
8788                 case Q3DEFORM_TEXT5:
8789                 case Q3DEFORM_TEXT6:
8790                 case Q3DEFORM_TEXT7:
8791                 case Q3DEFORM_NONE:
8792                         break;
8793                 case Q3DEFORM_AUTOSPRITE:
8794                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8795                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8796                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8797                         VectorNormalize(newforward);
8798                         VectorNormalize(newright);
8799                         VectorNormalize(newup);
8800 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8801 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8802 //                      rsurface.batchvertex3f_bufferoffset = 0;
8803 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8804 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8805 //                      rsurface.batchsvector3f_bufferoffset = 0;
8806 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8807 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8808 //                      rsurface.batchtvector3f_bufferoffset = 0;
8809 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8810 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8811 //                      rsurface.batchnormal3f_bufferoffset = 0;
8812                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8813                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8814                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8815                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8816                                 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);
8817                         // a single autosprite surface can contain multiple sprites...
8818                         for (j = 0;j < batchnumvertices - 3;j += 4)
8819                         {
8820                                 VectorClear(center);
8821                                 for (i = 0;i < 4;i++)
8822                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8823                                 VectorScale(center, 0.25f, center);
8824                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8825                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8826                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8827                                 for (i = 0;i < 4;i++)
8828                                 {
8829                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8830                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8831                                 }
8832                         }
8833                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8834                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8835                         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);
8836                         break;
8837                 case Q3DEFORM_AUTOSPRITE2:
8838                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8839                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8840                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8841                         VectorNormalize(newforward);
8842                         VectorNormalize(newright);
8843                         VectorNormalize(newup);
8844 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8845 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8846 //                      rsurface.batchvertex3f_bufferoffset = 0;
8847                         {
8848                                 const float *v1, *v2;
8849                                 vec3_t start, end;
8850                                 float f, l;
8851                                 struct
8852                                 {
8853                                         float length2;
8854                                         const float *v1;
8855                                         const float *v2;
8856                                 }
8857                                 shortest[2];
8858                                 memset(shortest, 0, sizeof(shortest));
8859                                 // a single autosprite surface can contain multiple sprites...
8860                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8861                                 {
8862                                         VectorClear(center);
8863                                         for (i = 0;i < 4;i++)
8864                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8865                                         VectorScale(center, 0.25f, center);
8866                                         // find the two shortest edges, then use them to define the
8867                                         // axis vectors for rotating around the central axis
8868                                         for (i = 0;i < 6;i++)
8869                                         {
8870                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8871                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8872                                                 l = VectorDistance2(v1, v2);
8873                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8874                                                 if (v1[2] != v2[2])
8875                                                         l += (1.0f / 1024.0f);
8876                                                 if (shortest[0].length2 > l || i == 0)
8877                                                 {
8878                                                         shortest[1] = shortest[0];
8879                                                         shortest[0].length2 = l;
8880                                                         shortest[0].v1 = v1;
8881                                                         shortest[0].v2 = v2;
8882                                                 }
8883                                                 else if (shortest[1].length2 > l || i == 1)
8884                                                 {
8885                                                         shortest[1].length2 = l;
8886                                                         shortest[1].v1 = v1;
8887                                                         shortest[1].v2 = v2;
8888                                                 }
8889                                         }
8890                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8891                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8892                                         // this calculates the right vector from the shortest edge
8893                                         // and the up vector from the edge midpoints
8894                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8895                                         VectorNormalize(right);
8896                                         VectorSubtract(end, start, up);
8897                                         VectorNormalize(up);
8898                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8899                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8900                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8901                                         VectorNegate(forward, forward);
8902                                         VectorReflect(forward, 0, up, forward);
8903                                         VectorNormalize(forward);
8904                                         CrossProduct(up, forward, newright);
8905                                         VectorNormalize(newright);
8906                                         // rotate the quad around the up axis vector, this is made
8907                                         // especially easy by the fact we know the quad is flat,
8908                                         // so we only have to subtract the center position and
8909                                         // measure distance along the right vector, and then
8910                                         // multiply that by the newright vector and add back the
8911                                         // center position
8912                                         // we also need to subtract the old position to undo the
8913                                         // displacement from the center, which we do with a
8914                                         // DotProduct, the subtraction/addition of center is also
8915                                         // optimized into DotProducts here
8916                                         l = DotProduct(right, center);
8917                                         for (i = 0;i < 4;i++)
8918                                         {
8919                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8920                                                 f = DotProduct(right, v1) - l;
8921                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8922                                         }
8923                                 }
8924                         }
8925                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8926                         {
8927 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8928 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8929 //                              rsurface.batchnormal3f_bufferoffset = 0;
8930                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8931                         }
8932                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8933                         {
8934 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8935 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8936 //                              rsurface.batchsvector3f_bufferoffset = 0;
8937 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8938 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8939 //                              rsurface.batchtvector3f_bufferoffset = 0;
8940                                 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);
8941                         }
8942                         break;
8943                 case Q3DEFORM_NORMAL:
8944                         // deform the normals to make reflections wavey
8945                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8946                         rsurface.batchnormal3f_vertexbuffer = NULL;
8947                         rsurface.batchnormal3f_bufferoffset = 0;
8948                         for (j = 0;j < batchnumvertices;j++)
8949                         {
8950                                 float vertex[3];
8951                                 float *normal = rsurface.batchnormal3f + 3*j;
8952                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8953                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8954                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8955                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8956                                 VectorNormalize(normal);
8957                         }
8958                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8959                         {
8960 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8961 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8962 //                              rsurface.batchsvector3f_bufferoffset = 0;
8963 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8964 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8965 //                              rsurface.batchtvector3f_bufferoffset = 0;
8966                                 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);
8967                         }
8968                         break;
8969                 case Q3DEFORM_WAVE:
8970                         // deform vertex array to make wavey water and flags and such
8971                         waveparms[0] = deform->waveparms[0];
8972                         waveparms[1] = deform->waveparms[1];
8973                         waveparms[2] = deform->waveparms[2];
8974                         waveparms[3] = deform->waveparms[3];
8975                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8976                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8977                         // this is how a divisor of vertex influence on deformation
8978                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8979                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8980 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8981 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8982 //                      rsurface.batchvertex3f_bufferoffset = 0;
8983 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8984 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8985 //                      rsurface.batchnormal3f_bufferoffset = 0;
8986                         for (j = 0;j < batchnumvertices;j++)
8987                         {
8988                                 // if the wavefunc depends on time, evaluate it per-vertex
8989                                 if (waveparms[3])
8990                                 {
8991                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8992                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8993                                 }
8994                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8995                         }
8996                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8997                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8999                         {
9000 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9001 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9002 //                              rsurface.batchsvector3f_bufferoffset = 0;
9003 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9004 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9005 //                              rsurface.batchtvector3f_bufferoffset = 0;
9006                                 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);
9007                         }
9008                         break;
9009                 case Q3DEFORM_BULGE:
9010                         // deform vertex array to make the surface have moving bulges
9011 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9012 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9013 //                      rsurface.batchvertex3f_bufferoffset = 0;
9014 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9015 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9016 //                      rsurface.batchnormal3f_bufferoffset = 0;
9017                         for (j = 0;j < batchnumvertices;j++)
9018                         {
9019                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9020                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9021                         }
9022                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9023                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9024                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9025                         {
9026 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9027 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9028 //                              rsurface.batchsvector3f_bufferoffset = 0;
9029 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9030 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9031 //                              rsurface.batchtvector3f_bufferoffset = 0;
9032                                 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);
9033                         }
9034                         break;
9035                 case Q3DEFORM_MOVE:
9036                         // deform vertex array
9037                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9038                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9039                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9040                         VectorScale(deform->parms, scale, waveparms);
9041 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9042 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9043 //                      rsurface.batchvertex3f_bufferoffset = 0;
9044                         for (j = 0;j < batchnumvertices;j++)
9045                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9046                         break;
9047                 }
9048         }
9049
9050         // generate texcoords based on the chosen texcoord source
9051         switch(rsurface.texture->tcgen.tcgen)
9052         {
9053         default:
9054         case Q3TCGEN_TEXTURE:
9055                 break;
9056         case Q3TCGEN_LIGHTMAP:
9057 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9058 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9059 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9060                 if (rsurface.batchtexcoordlightmap2f)
9061                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9062                 break;
9063         case Q3TCGEN_VECTOR:
9064 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9065 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9066 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9067                 for (j = 0;j < batchnumvertices;j++)
9068                 {
9069                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9070                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9071                 }
9072                 break;
9073         case Q3TCGEN_ENVIRONMENT:
9074                 // make environment reflections using a spheremap
9075                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9076                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9077                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9078                 for (j = 0;j < batchnumvertices;j++)
9079                 {
9080                         // identical to Q3A's method, but executed in worldspace so
9081                         // carried models can be shiny too
9082
9083                         float viewer[3], d, reflected[3], worldreflected[3];
9084
9085                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9086                         // VectorNormalize(viewer);
9087
9088                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9089
9090                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9091                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9092                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9093                         // note: this is proportinal to viewer, so we can normalize later
9094
9095                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9096                         VectorNormalize(worldreflected);
9097
9098                         // note: this sphere map only uses world x and z!
9099                         // so positive and negative y will LOOK THE SAME.
9100                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9101                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9102                 }
9103                 break;
9104         }
9105         // the only tcmod that needs software vertex processing is turbulent, so
9106         // check for it here and apply the changes if needed
9107         // and we only support that as the first one
9108         // (handling a mixture of turbulent and other tcmods would be problematic
9109         //  without punting it entirely to a software path)
9110         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9111         {
9112                 amplitude = rsurface.texture->tcmods[0].parms[1];
9113                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9114 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9115 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9116 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9117                 for (j = 0;j < batchnumvertices;j++)
9118                 {
9119                         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);
9120                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9121                 }
9122         }
9123
9124         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9125         {
9126                 // convert the modified arrays to vertex structs
9127 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9128 //              rsurface.batchvertexmeshbuffer = NULL;
9129                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9130                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9131                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9132                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9133                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9134                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9135                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9136                 {
9137                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9138                         {
9139                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9140                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9141                         }
9142                 }
9143                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9144                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9145                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9146                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9147                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9148                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9149                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9150                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9151                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9152         }
9153 }
9154
9155 void RSurf_DrawBatch(void)
9156 {
9157         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9158         // through the pipeline, killing it earlier in the pipeline would have
9159         // per-surface overhead rather than per-batch overhead, so it's best to
9160         // reject it here, before it hits glDraw.
9161         if (rsurface.batchnumtriangles == 0)
9162                 return;
9163 #if 0
9164         // batch debugging code
9165         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9166         {
9167                 int i;
9168                 int j;
9169                 int c;
9170                 const int *e;
9171                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9172                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9173                 {
9174                         c = e[i];
9175                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9176                         {
9177                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9178                                 {
9179                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9180                                                 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);
9181                                         break;
9182                                 }
9183                         }
9184                 }
9185         }
9186 #endif
9187         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);
9188 }
9189
9190 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9191 {
9192         // pick the closest matching water plane
9193         int planeindex, vertexindex, bestplaneindex = -1;
9194         float d, bestd;
9195         vec3_t vert;
9196         const float *v;
9197         r_waterstate_waterplane_t *p;
9198         qboolean prepared = false;
9199         bestd = 0;
9200         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9201         {
9202                 if(p->camera_entity != rsurface.texture->camera_entity)
9203                         continue;
9204                 d = 0;
9205                 if(!prepared)
9206                 {
9207                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9208                         prepared = true;
9209                         if(rsurface.batchnumvertices == 0)
9210                                 break;
9211                 }
9212                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9213                 {
9214                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9215                         d += fabs(PlaneDiff(vert, &p->plane));
9216                 }
9217                 if (bestd > d || bestplaneindex < 0)
9218                 {
9219                         bestd = d;
9220                         bestplaneindex = planeindex;
9221                 }
9222         }
9223         return bestplaneindex;
9224         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9225         // this situation though, as it might be better to render single larger
9226         // batches with useless stuff (backface culled for example) than to
9227         // render multiple smaller batches
9228 }
9229
9230 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9231 {
9232         int i;
9233         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9234         rsurface.passcolor4f_vertexbuffer = 0;
9235         rsurface.passcolor4f_bufferoffset = 0;
9236         for (i = 0;i < rsurface.batchnumvertices;i++)
9237                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9238 }
9239
9240 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9241 {
9242         int i;
9243         float f;
9244         const float *v;
9245         const float *c;
9246         float *c2;
9247         if (rsurface.passcolor4f)
9248         {
9249                 // generate color arrays
9250                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9251                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9252                 rsurface.passcolor4f_vertexbuffer = 0;
9253                 rsurface.passcolor4f_bufferoffset = 0;
9254                 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)
9255                 {
9256                         f = RSurf_FogVertex(v);
9257                         c2[0] = c[0] * f;
9258                         c2[1] = c[1] * f;
9259                         c2[2] = c[2] * f;
9260                         c2[3] = c[3];
9261                 }
9262         }
9263         else
9264         {
9265                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9266                 rsurface.passcolor4f_vertexbuffer = 0;
9267                 rsurface.passcolor4f_bufferoffset = 0;
9268                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9269                 {
9270                         f = RSurf_FogVertex(v);
9271                         c2[0] = f;
9272                         c2[1] = f;
9273                         c2[2] = f;
9274                         c2[3] = 1;
9275                 }
9276         }
9277 }
9278
9279 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9280 {
9281         int i;
9282         float f;
9283         const float *v;
9284         const float *c;
9285         float *c2;
9286         if (!rsurface.passcolor4f)
9287                 return;
9288         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9289         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9290         rsurface.passcolor4f_vertexbuffer = 0;
9291         rsurface.passcolor4f_bufferoffset = 0;
9292         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)
9293         {
9294                 f = RSurf_FogVertex(v);
9295                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9296                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9297                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9298                 c2[3] = c[3];
9299         }
9300 }
9301
9302 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9303 {
9304         int i;
9305         const float *c;
9306         float *c2;
9307         if (!rsurface.passcolor4f)
9308                 return;
9309         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9310         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9311         rsurface.passcolor4f_vertexbuffer = 0;
9312         rsurface.passcolor4f_bufferoffset = 0;
9313         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9314         {
9315                 c2[0] = c[0] * r;
9316                 c2[1] = c[1] * g;
9317                 c2[2] = c[2] * b;
9318                 c2[3] = c[3] * a;
9319         }
9320 }
9321
9322 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9323 {
9324         int i;
9325         const float *c;
9326         float *c2;
9327         if (!rsurface.passcolor4f)
9328                 return;
9329         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9330         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9331         rsurface.passcolor4f_vertexbuffer = 0;
9332         rsurface.passcolor4f_bufferoffset = 0;
9333         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9334         {
9335                 c2[0] = c[0] + r_refdef.scene.ambient;
9336                 c2[1] = c[1] + r_refdef.scene.ambient;
9337                 c2[2] = c[2] + r_refdef.scene.ambient;
9338                 c2[3] = c[3];
9339         }
9340 }
9341
9342 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9343 {
9344         // TODO: optimize
9345         rsurface.passcolor4f = NULL;
9346         rsurface.passcolor4f_vertexbuffer = 0;
9347         rsurface.passcolor4f_bufferoffset = 0;
9348         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9349         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9350         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9351         GL_Color(r, g, b, a);
9352         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9353         RSurf_DrawBatch();
9354 }
9355
9356 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9357 {
9358         // TODO: optimize applyfog && applycolor case
9359         // just apply fog if necessary, and tint the fog color array if necessary
9360         rsurface.passcolor4f = NULL;
9361         rsurface.passcolor4f_vertexbuffer = 0;
9362         rsurface.passcolor4f_bufferoffset = 0;
9363         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9364         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9365         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9366         GL_Color(r, g, b, a);
9367         RSurf_DrawBatch();
9368 }
9369
9370 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9371 {
9372         // TODO: optimize
9373         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9374         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9375         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9376         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9377         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9378         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9379         GL_Color(r, g, b, a);
9380         RSurf_DrawBatch();
9381 }
9382
9383 static void RSurf_DrawBatch_GL11_ClampColor(void)
9384 {
9385         int i;
9386         const float *c1;
9387         float *c2;
9388         if (!rsurface.passcolor4f)
9389                 return;
9390         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9391         {
9392                 c2[0] = bound(0.0f, c1[0], 1.0f);
9393                 c2[1] = bound(0.0f, c1[1], 1.0f);
9394                 c2[2] = bound(0.0f, c1[2], 1.0f);
9395                 c2[3] = bound(0.0f, c1[3], 1.0f);
9396         }
9397 }
9398
9399 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9400 {
9401         int i;
9402         float f;
9403         const float *v;
9404         const float *n;
9405         float *c;
9406         //vec3_t eyedir;
9407
9408         // fake shading
9409         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9410         rsurface.passcolor4f_vertexbuffer = 0;
9411         rsurface.passcolor4f_bufferoffset = 0;
9412         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)
9413         {
9414                 f = -DotProduct(r_refdef.view.forward, n);
9415                 f = max(0, f);
9416                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9417                 f *= r_refdef.lightmapintensity;
9418                 Vector4Set(c, f, f, f, 1);
9419         }
9420 }
9421
9422 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9423 {
9424         RSurf_DrawBatch_GL11_ApplyFakeLight();
9425         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9426         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9427         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9428         GL_Color(r, g, b, a);
9429         RSurf_DrawBatch();
9430 }
9431
9432 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9433 {
9434         int i;
9435         float f;
9436         float alpha;
9437         const float *v;
9438         const float *n;
9439         float *c;
9440         vec3_t ambientcolor;
9441         vec3_t diffusecolor;
9442         vec3_t lightdir;
9443         // TODO: optimize
9444         // model lighting
9445         VectorCopy(rsurface.modellight_lightdir, lightdir);
9446         f = 0.5f * r_refdef.lightmapintensity;
9447         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9448         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9449         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9450         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9451         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9452         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9453         alpha = *a;
9454         if (VectorLength2(diffusecolor) > 0)
9455         {
9456                 // q3-style directional shading
9457                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9458                 rsurface.passcolor4f_vertexbuffer = 0;
9459                 rsurface.passcolor4f_bufferoffset = 0;
9460                 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)
9461                 {
9462                         if ((f = DotProduct(n, lightdir)) > 0)
9463                                 VectorMA(ambientcolor, f, diffusecolor, c);
9464                         else
9465                                 VectorCopy(ambientcolor, c);
9466                         c[3] = alpha;
9467                 }
9468                 *r = 1;
9469                 *g = 1;
9470                 *b = 1;
9471                 *a = 1;
9472                 *applycolor = false;
9473         }
9474         else
9475         {
9476                 *r = ambientcolor[0];
9477                 *g = ambientcolor[1];
9478                 *b = ambientcolor[2];
9479                 rsurface.passcolor4f = NULL;
9480                 rsurface.passcolor4f_vertexbuffer = 0;
9481                 rsurface.passcolor4f_bufferoffset = 0;
9482         }
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9486 {
9487         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9488         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9489         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9490         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9491         GL_Color(r, g, b, a);
9492         RSurf_DrawBatch();
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9496 {
9497         int i;
9498         float f;
9499         const float *v;
9500         float *c;
9501
9502         // fake shading
9503         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9504         rsurface.passcolor4f_vertexbuffer = 0;
9505         rsurface.passcolor4f_bufferoffset = 0;
9506
9507         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9508         {
9509                 f = 1 - RSurf_FogVertex(v);
9510                 c[0] = r;
9511                 c[1] = g;
9512                 c[2] = b;
9513                 c[3] = f * a;
9514         }
9515 }
9516
9517 void RSurf_SetupDepthAndCulling(void)
9518 {
9519         // submodels are biased to avoid z-fighting with world surfaces that they
9520         // may be exactly overlapping (avoids z-fighting artifacts on certain
9521         // doors and things in Quake maps)
9522         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9523         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9524         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9525         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9526 }
9527
9528 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9529 {
9530         // transparent sky would be ridiculous
9531         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9532                 return;
9533         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9534         skyrenderlater = true;
9535         RSurf_SetupDepthAndCulling();
9536         GL_DepthMask(true);
9537         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9538         // skymasking on them, and Quake3 never did sky masking (unlike
9539         // software Quake and software Quake2), so disable the sky masking
9540         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9541         // and skymasking also looks very bad when noclipping outside the
9542         // level, so don't use it then either.
9543         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9544         {
9545                 R_Mesh_ResetTextureState();
9546                 if (skyrendermasked)
9547                 {
9548                         R_SetupShader_DepthOrShadow(false);
9549                         // depth-only (masking)
9550                         GL_ColorMask(0,0,0,0);
9551                         // just to make sure that braindead drivers don't draw
9552                         // anything despite that colormask...
9553                         GL_BlendFunc(GL_ZERO, GL_ONE);
9554                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9555                         if (rsurface.batchvertex3fbuffer)
9556                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9557                         else
9558                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9559                 }
9560                 else
9561                 {
9562                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9563                         // fog sky
9564                         GL_BlendFunc(GL_ONE, GL_ZERO);
9565                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9566                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9567                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9568                 }
9569                 RSurf_DrawBatch();
9570                 if (skyrendermasked)
9571                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9572         }
9573         R_Mesh_ResetTextureState();
9574         GL_Color(1, 1, 1, 1);
9575 }
9576
9577 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9578 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9579 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9580 {
9581         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9582                 return;
9583         if (prepass)
9584         {
9585                 // render screenspace normalmap to texture
9586                 GL_DepthMask(true);
9587                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9588                 RSurf_DrawBatch();
9589         }
9590
9591         // bind lightmap texture
9592
9593         // water/refraction/reflection/camera surfaces have to be handled specially
9594         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9595         {
9596                 int start, end, startplaneindex;
9597                 for (start = 0;start < texturenumsurfaces;start = end)
9598                 {
9599                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9600                         if(startplaneindex < 0)
9601                         {
9602                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9603                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9604                                 end = start + 1;
9605                                 continue;
9606                         }
9607                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9608                                 ;
9609                         // now that we have a batch using the same planeindex, render it
9610                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9611                         {
9612                                 // render water or distortion background
9613                                 GL_DepthMask(true);
9614                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9615                                 RSurf_DrawBatch();
9616                                 // blend surface on top
9617                                 GL_DepthMask(false);
9618                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9619                                 RSurf_DrawBatch();
9620                         }
9621                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9622                         {
9623                                 // render surface with reflection texture as input
9624                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9625                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9626                                 RSurf_DrawBatch();
9627                         }
9628                 }
9629                 return;
9630         }
9631
9632         // render surface batch normally
9633         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9634         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9635         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9636                 GL_AlphaTest(true);
9637         RSurf_DrawBatch();
9638         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9639                 GL_AlphaTest(false);
9640 }
9641
9642 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9643 {
9644         // OpenGL 1.3 path - anything not completely ancient
9645         qboolean applycolor;
9646         qboolean applyfog;
9647         int layerindex;
9648         const texturelayer_t *layer;
9649         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);
9650         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9651
9652         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9653         {
9654                 vec4_t layercolor;
9655                 int layertexrgbscale;
9656                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9657                 {
9658                         if (layerindex == 0)
9659                                 GL_AlphaTest(true);
9660                         else
9661                         {
9662                                 GL_AlphaTest(false);
9663                                 GL_DepthFunc(GL_EQUAL);
9664                         }
9665                 }
9666                 GL_DepthMask(layer->depthmask && writedepth);
9667                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9668                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9669                 {
9670                         layertexrgbscale = 4;
9671                         VectorScale(layer->color, 0.25f, layercolor);
9672                 }
9673                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9674                 {
9675                         layertexrgbscale = 2;
9676                         VectorScale(layer->color, 0.5f, layercolor);
9677                 }
9678                 else
9679                 {
9680                         layertexrgbscale = 1;
9681                         VectorScale(layer->color, 1.0f, layercolor);
9682                 }
9683                 layercolor[3] = layer->color[3];
9684                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9685                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9686                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9687                 switch (layer->type)
9688                 {
9689                 case TEXTURELAYERTYPE_LITTEXTURE:
9690                         // single-pass lightmapped texture with 2x rgbscale
9691                         R_Mesh_TexBind(0, r_texture_white);
9692                         R_Mesh_TexMatrix(0, NULL);
9693                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9694                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9695                         R_Mesh_TexBind(1, layer->texture);
9696                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9697                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9698                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9700                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9701                         else if (FAKELIGHT_ENABLED)
9702                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9703                         else if (rsurface.uselightmaptexture)
9704                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9705                         else
9706                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9707                         break;
9708                 case TEXTURELAYERTYPE_TEXTURE:
9709                         // singletexture unlit texture with transparency support
9710                         R_Mesh_TexBind(0, layer->texture);
9711                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9712                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9713                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9714                         R_Mesh_TexBind(1, 0);
9715                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9716                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9717                         break;
9718                 case TEXTURELAYERTYPE_FOG:
9719                         // singletexture fogging
9720                         if (layer->texture)
9721                         {
9722                                 R_Mesh_TexBind(0, layer->texture);
9723                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9724                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9725                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9726                         }
9727                         else
9728                         {
9729                                 R_Mesh_TexBind(0, 0);
9730                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9731                         }
9732                         R_Mesh_TexBind(1, 0);
9733                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9734                         // generate a color array for the fog pass
9735                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9736                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9737                         RSurf_DrawBatch();
9738                         break;
9739                 default:
9740                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9741                 }
9742         }
9743         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9744         {
9745                 GL_DepthFunc(GL_LEQUAL);
9746                 GL_AlphaTest(false);
9747         }
9748 }
9749
9750 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9751 {
9752         // OpenGL 1.1 - crusty old voodoo path
9753         qboolean applyfog;
9754         int layerindex;
9755         const texturelayer_t *layer;
9756         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);
9757         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9758
9759         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9760         {
9761                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9762                 {
9763                         if (layerindex == 0)
9764                                 GL_AlphaTest(true);
9765                         else
9766                         {
9767                                 GL_AlphaTest(false);
9768                                 GL_DepthFunc(GL_EQUAL);
9769                         }
9770                 }
9771                 GL_DepthMask(layer->depthmask && writedepth);
9772                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9773                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9774                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9775                 switch (layer->type)
9776                 {
9777                 case TEXTURELAYERTYPE_LITTEXTURE:
9778                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9779                         {
9780                                 // two-pass lit texture with 2x rgbscale
9781                                 // first the lightmap pass
9782                                 R_Mesh_TexBind(0, r_texture_white);
9783                                 R_Mesh_TexMatrix(0, NULL);
9784                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9785                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9786                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9787                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9788                                 else if (FAKELIGHT_ENABLED)
9789                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9790                                 else if (rsurface.uselightmaptexture)
9791                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9792                                 else
9793                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9794                                 // then apply the texture to it
9795                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9796                                 R_Mesh_TexBind(0, layer->texture);
9797                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9798                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9799                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9800                                 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);
9801                         }
9802                         else
9803                         {
9804                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9805                                 R_Mesh_TexBind(0, layer->texture);
9806                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9807                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9808                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9809                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9810                                         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);
9811                                 else
9812                                         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);
9813                         }
9814                         break;
9815                 case TEXTURELAYERTYPE_TEXTURE:
9816                         // singletexture unlit texture with transparency support
9817                         R_Mesh_TexBind(0, layer->texture);
9818                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9819                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9820                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9821                         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);
9822                         break;
9823                 case TEXTURELAYERTYPE_FOG:
9824                         // singletexture fogging
9825                         if (layer->texture)
9826                         {
9827                                 R_Mesh_TexBind(0, layer->texture);
9828                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9829                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9830                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9831                         }
9832                         else
9833                         {
9834                                 R_Mesh_TexBind(0, 0);
9835                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9836                         }
9837                         // generate a color array for the fog pass
9838                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9839                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9840                         RSurf_DrawBatch();
9841                         break;
9842                 default:
9843                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9844                 }
9845         }
9846         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9847         {
9848                 GL_DepthFunc(GL_LEQUAL);
9849                 GL_AlphaTest(false);
9850         }
9851 }
9852
9853 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9854 {
9855         int vi;
9856         int j;
9857         r_vertexgeneric_t *batchvertex;
9858         float c[4];
9859
9860 //      R_Mesh_ResetTextureState();
9861         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9862
9863         if(rsurface.texture && rsurface.texture->currentskinframe)
9864         {
9865                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9866                 c[3] *= rsurface.texture->currentalpha;
9867         }
9868         else
9869         {
9870                 c[0] = 1;
9871                 c[1] = 0;
9872                 c[2] = 1;
9873                 c[3] = 1;
9874         }
9875
9876         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9877         {
9878                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9879                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9880                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9881         }
9882
9883         // brighten it up (as texture value 127 means "unlit")
9884         c[0] *= 2 * r_refdef.view.colorscale;
9885         c[1] *= 2 * r_refdef.view.colorscale;
9886         c[2] *= 2 * r_refdef.view.colorscale;
9887
9888         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9889                 c[3] *= r_wateralpha.value;
9890
9891         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9892         {
9893                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9894                 GL_DepthMask(false);
9895         }
9896         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9897         {
9898                 GL_BlendFunc(GL_ONE, GL_ONE);
9899                 GL_DepthMask(false);
9900         }
9901         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9902         {
9903                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9904                 GL_DepthMask(false);
9905         }
9906         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9907         {
9908                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9909                 GL_DepthMask(false);
9910         }
9911         else
9912         {
9913                 GL_BlendFunc(GL_ONE, GL_ZERO);
9914                 GL_DepthMask(writedepth);
9915         }
9916
9917         if (r_showsurfaces.integer == 3)
9918         {
9919                 rsurface.passcolor4f = NULL;
9920
9921                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9922                 {
9923                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9924
9925                         rsurface.passcolor4f = NULL;
9926                         rsurface.passcolor4f_vertexbuffer = 0;
9927                         rsurface.passcolor4f_bufferoffset = 0;
9928                 }
9929                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9930                 {
9931                         qboolean applycolor = true;
9932                         float one = 1.0;
9933
9934                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9935
9936                         r_refdef.lightmapintensity = 1;
9937                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9938                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9939                 }
9940                 else if (FAKELIGHT_ENABLED)
9941                 {
9942                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9943
9944                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9945                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9946                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9947                 }
9948                 else
9949                 {
9950                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9951
9952                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9953                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9954                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9955                 }
9956
9957                 if(!rsurface.passcolor4f)
9958                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9959
9960                 RSurf_DrawBatch_GL11_ApplyAmbient();
9961                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9962                 if(r_refdef.fogenabled)
9963                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9964                 RSurf_DrawBatch_GL11_ClampColor();
9965
9966                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9967                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9968                 RSurf_DrawBatch();
9969         }
9970         else if (!r_refdef.view.showdebug)
9971         {
9972                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9973                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9974                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9975                 {
9976                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9977                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9978                 }
9979                 R_Mesh_PrepareVertices_Generic_Unlock();
9980                 RSurf_DrawBatch();
9981         }
9982         else if (r_showsurfaces.integer == 4)
9983         {
9984                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9985                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9986                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9987                 {
9988                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9989                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9990                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9991                 }
9992                 R_Mesh_PrepareVertices_Generic_Unlock();
9993                 RSurf_DrawBatch();
9994         }
9995         else if (r_showsurfaces.integer == 2)
9996         {
9997                 const int *e;
9998                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9999                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10000                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10001                 {
10002                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10003                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10004                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10005                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10006                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10007                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10008                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10009                 }
10010                 R_Mesh_PrepareVertices_Generic_Unlock();
10011                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10012         }
10013         else
10014         {
10015                 int texturesurfaceindex;
10016                 int k;
10017                 const msurface_t *surface;
10018                 float surfacecolor4f[4];
10019                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10020                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10021                 vi = 0;
10022                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10023                 {
10024                         surface = texturesurfacelist[texturesurfaceindex];
10025                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10026                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10027                         for (j = 0;j < surface->num_vertices;j++)
10028                         {
10029                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10030                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10031                                 vi++;
10032                         }
10033                 }
10034                 R_Mesh_PrepareVertices_Generic_Unlock();
10035                 RSurf_DrawBatch();
10036         }
10037 }
10038
10039 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10040 {
10041         CHECKGLERROR
10042         RSurf_SetupDepthAndCulling();
10043         if (r_showsurfaces.integer)
10044         {
10045                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10046                 return;
10047         }
10048         switch (vid.renderpath)
10049         {
10050         case RENDERPATH_GL20:
10051         case RENDERPATH_D3D9:
10052         case RENDERPATH_D3D10:
10053         case RENDERPATH_D3D11:
10054         case RENDERPATH_SOFT:
10055         case RENDERPATH_GLES2:
10056                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10057                 break;
10058         case RENDERPATH_GL13:
10059         case RENDERPATH_GLES1:
10060                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10061                 break;
10062         case RENDERPATH_GL11:
10063                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10064                 break;
10065         }
10066         CHECKGLERROR
10067 }
10068
10069 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10070 {
10071         CHECKGLERROR
10072         RSurf_SetupDepthAndCulling();
10073         if (r_showsurfaces.integer)
10074         {
10075                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10076                 return;
10077         }
10078         switch (vid.renderpath)
10079         {
10080         case RENDERPATH_GL20:
10081         case RENDERPATH_D3D9:
10082         case RENDERPATH_D3D10:
10083         case RENDERPATH_D3D11:
10084         case RENDERPATH_SOFT:
10085         case RENDERPATH_GLES2:
10086                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10087                 break;
10088         case RENDERPATH_GL13:
10089         case RENDERPATH_GLES1:
10090                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10091                 break;
10092         case RENDERPATH_GL11:
10093                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10094                 break;
10095         }
10096         CHECKGLERROR
10097 }
10098
10099 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10100 {
10101         int i, j;
10102         int texturenumsurfaces, endsurface;
10103         texture_t *texture;
10104         const msurface_t *surface;
10105         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10106
10107         // if the model is static it doesn't matter what value we give for
10108         // wantnormals and wanttangents, so this logic uses only rules applicable
10109         // to a model, knowing that they are meaningless otherwise
10110         if (ent == r_refdef.scene.worldentity)
10111                 RSurf_ActiveWorldEntity();
10112         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10113                 RSurf_ActiveModelEntity(ent, false, false, false);
10114         else
10115         {
10116                 switch (vid.renderpath)
10117                 {
10118                 case RENDERPATH_GL20:
10119                 case RENDERPATH_D3D9:
10120                 case RENDERPATH_D3D10:
10121                 case RENDERPATH_D3D11:
10122                 case RENDERPATH_SOFT:
10123                 case RENDERPATH_GLES2:
10124                         RSurf_ActiveModelEntity(ent, true, true, false);
10125                         break;
10126                 case RENDERPATH_GL11:
10127                 case RENDERPATH_GL13:
10128                 case RENDERPATH_GLES1:
10129                         RSurf_ActiveModelEntity(ent, true, false, false);
10130                         break;
10131                 }
10132         }
10133
10134         if (r_transparentdepthmasking.integer)
10135         {
10136                 qboolean setup = false;
10137                 for (i = 0;i < numsurfaces;i = j)
10138                 {
10139                         j = i + 1;
10140                         surface = rsurface.modelsurfaces + surfacelist[i];
10141                         texture = surface->texture;
10142                         rsurface.texture = R_GetCurrentTexture(texture);
10143                         rsurface.lightmaptexture = NULL;
10144                         rsurface.deluxemaptexture = NULL;
10145                         rsurface.uselightmaptexture = false;
10146                         // scan ahead until we find a different texture
10147                         endsurface = min(i + 1024, numsurfaces);
10148                         texturenumsurfaces = 0;
10149                         texturesurfacelist[texturenumsurfaces++] = surface;
10150                         for (;j < endsurface;j++)
10151                         {
10152                                 surface = rsurface.modelsurfaces + surfacelist[j];
10153                                 if (texture != surface->texture)
10154                                         break;
10155                                 texturesurfacelist[texturenumsurfaces++] = surface;
10156                         }
10157                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10158                                 continue;
10159                         // render the range of surfaces as depth
10160                         if (!setup)
10161                         {
10162                                 setup = true;
10163                                 GL_ColorMask(0,0,0,0);
10164                                 GL_Color(1,1,1,1);
10165                                 GL_DepthTest(true);
10166                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10167                                 GL_DepthMask(true);
10168 //                              R_Mesh_ResetTextureState();
10169                                 R_SetupShader_DepthOrShadow(false);
10170                         }
10171                         RSurf_SetupDepthAndCulling();
10172                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10173                         if (rsurface.batchvertex3fbuffer)
10174                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10175                         else
10176                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10177                         RSurf_DrawBatch();
10178                 }
10179                 if (setup)
10180                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10181         }
10182
10183         for (i = 0;i < numsurfaces;i = j)
10184         {
10185                 j = i + 1;
10186                 surface = rsurface.modelsurfaces + surfacelist[i];
10187                 texture = surface->texture;
10188                 rsurface.texture = R_GetCurrentTexture(texture);
10189                 // scan ahead until we find a different texture
10190                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10191                 texturenumsurfaces = 0;
10192                 texturesurfacelist[texturenumsurfaces++] = surface;
10193                 if(FAKELIGHT_ENABLED)
10194                 {
10195                         rsurface.lightmaptexture = NULL;
10196                         rsurface.deluxemaptexture = NULL;
10197                         rsurface.uselightmaptexture = false;
10198                         for (;j < endsurface;j++)
10199                         {
10200                                 surface = rsurface.modelsurfaces + surfacelist[j];
10201                                 if (texture != surface->texture)
10202                                         break;
10203                                 texturesurfacelist[texturenumsurfaces++] = surface;
10204                         }
10205                 }
10206                 else
10207                 {
10208                         rsurface.lightmaptexture = surface->lightmaptexture;
10209                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10210                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10211                         for (;j < endsurface;j++)
10212                         {
10213                                 surface = rsurface.modelsurfaces + surfacelist[j];
10214                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10215                                         break;
10216                                 texturesurfacelist[texturenumsurfaces++] = surface;
10217                         }
10218                 }
10219                 // render the range of surfaces
10220                 if (ent == r_refdef.scene.worldentity)
10221                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10222                 else
10223                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10224         }
10225         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10226 }
10227
10228 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10229 {
10230         // transparent surfaces get pushed off into the transparent queue
10231         int surfacelistindex;
10232         const msurface_t *surface;
10233         vec3_t tempcenter, center;
10234         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10235         {
10236                 surface = texturesurfacelist[surfacelistindex];
10237                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10238                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10239                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10240                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10241                 if (queueentity->transparent_offset) // transparent offset
10242                 {
10243                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10244                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10245                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10246                 }
10247                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10248         }
10249 }
10250
10251 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10252 {
10253         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10254                 return;
10255         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10256                 return;
10257         RSurf_SetupDepthAndCulling();
10258         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10259         if (rsurface.batchvertex3fbuffer)
10260                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10261         else
10262                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10263         RSurf_DrawBatch();
10264 }
10265
10266 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10267 {
10268         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10269         CHECKGLERROR
10270         if (depthonly)
10271                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10272         else if (prepass)
10273         {
10274                 if (!rsurface.texture->currentnumlayers)
10275                         return;
10276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10277                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10278                 else
10279                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10280         }
10281         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10282                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10283         else if (!rsurface.texture->currentnumlayers)
10284                 return;
10285         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10286         {
10287                 // in the deferred case, transparent surfaces were queued during prepass
10288                 if (!r_shadow_usingdeferredprepass)
10289                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10290         }
10291         else
10292         {
10293                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10294                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10295         }
10296         CHECKGLERROR
10297 }
10298
10299 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10300 {
10301         int i, j;
10302         texture_t *texture;
10303         R_FrameData_SetMark();
10304         // break the surface list down into batches by texture and use of lightmapping
10305         for (i = 0;i < numsurfaces;i = j)
10306         {
10307                 j = i + 1;
10308                 // texture is the base texture pointer, rsurface.texture is the
10309                 // current frame/skin the texture is directing us to use (for example
10310                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10311                 // use skin 1 instead)
10312                 texture = surfacelist[i]->texture;
10313                 rsurface.texture = R_GetCurrentTexture(texture);
10314                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10315                 {
10316                         // if this texture is not the kind we want, skip ahead to the next one
10317                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10318                                 ;
10319                         continue;
10320                 }
10321                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10322                 {
10323                         rsurface.lightmaptexture = NULL;
10324                         rsurface.deluxemaptexture = NULL;
10325                         rsurface.uselightmaptexture = false;
10326                         // simply scan ahead until we find a different texture or lightmap state
10327                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10328                                 ;
10329                 }
10330                 else
10331                 {
10332                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10333                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10334                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10335                         // simply scan ahead until we find a different texture or lightmap state
10336                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10337                                 ;
10338                 }
10339                 // render the range of surfaces
10340                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10341         }
10342         R_FrameData_ReturnToMark();
10343 }
10344
10345 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10346 {
10347         CHECKGLERROR
10348         if (depthonly)
10349                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10350         else if (prepass)
10351         {
10352                 if (!rsurface.texture->currentnumlayers)
10353                         return;
10354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10355                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10356                 else
10357                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10358         }
10359         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10360                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10361         else if (!rsurface.texture->currentnumlayers)
10362                 return;
10363         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10364         {
10365                 // in the deferred case, transparent surfaces were queued during prepass
10366                 if (!r_shadow_usingdeferredprepass)
10367                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10368         }
10369         else
10370         {
10371                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10372                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10373         }
10374         CHECKGLERROR
10375 }
10376
10377 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10378 {
10379         int i, j;
10380         texture_t *texture;
10381         R_FrameData_SetMark();
10382         // break the surface list down into batches by texture and use of lightmapping
10383         for (i = 0;i < numsurfaces;i = j)
10384         {
10385                 j = i + 1;
10386                 // texture is the base texture pointer, rsurface.texture is the
10387                 // current frame/skin the texture is directing us to use (for example
10388                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10389                 // use skin 1 instead)
10390                 texture = surfacelist[i]->texture;
10391                 rsurface.texture = R_GetCurrentTexture(texture);
10392                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10393                 {
10394                         // if this texture is not the kind we want, skip ahead to the next one
10395                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10396                                 ;
10397                         continue;
10398                 }
10399                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10400                 {
10401                         rsurface.lightmaptexture = NULL;
10402                         rsurface.deluxemaptexture = NULL;
10403                         rsurface.uselightmaptexture = false;
10404                         // simply scan ahead until we find a different texture or lightmap state
10405                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10406                                 ;
10407                 }
10408                 else
10409                 {
10410                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10411                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10412                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10413                         // simply scan ahead until we find a different texture or lightmap state
10414                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10415                                 ;
10416                 }
10417                 // render the range of surfaces
10418                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10419         }
10420         R_FrameData_ReturnToMark();
10421 }
10422
10423 float locboxvertex3f[6*4*3] =
10424 {
10425         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10426         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10427         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10428         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10429         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10430         1,0,0, 0,0,0, 0,1,0, 1,1,0
10431 };
10432
10433 unsigned short locboxelements[6*2*3] =
10434 {
10435          0, 1, 2, 0, 2, 3,
10436          4, 5, 6, 4, 6, 7,
10437          8, 9,10, 8,10,11,
10438         12,13,14, 12,14,15,
10439         16,17,18, 16,18,19,
10440         20,21,22, 20,22,23
10441 };
10442
10443 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10444 {
10445         int i, j;
10446         cl_locnode_t *loc = (cl_locnode_t *)ent;
10447         vec3_t mins, size;
10448         float vertex3f[6*4*3];
10449         CHECKGLERROR
10450         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10451         GL_DepthMask(false);
10452         GL_DepthRange(0, 1);
10453         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10454         GL_DepthTest(true);
10455         GL_CullFace(GL_NONE);
10456         R_EntityMatrix(&identitymatrix);
10457
10458 //      R_Mesh_ResetTextureState();
10459
10460         i = surfacelist[0];
10461         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10462                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10463                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10464                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10465
10466         if (VectorCompare(loc->mins, loc->maxs))
10467         {
10468                 VectorSet(size, 2, 2, 2);
10469                 VectorMA(loc->mins, -0.5f, size, mins);
10470         }
10471         else
10472         {
10473                 VectorCopy(loc->mins, mins);
10474                 VectorSubtract(loc->maxs, loc->mins, size);
10475         }
10476
10477         for (i = 0;i < 6*4*3;)
10478                 for (j = 0;j < 3;j++, i++)
10479                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10480
10481         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10482         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10483         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10484 }
10485
10486 void R_DrawLocs(void)
10487 {
10488         int index;
10489         cl_locnode_t *loc, *nearestloc;
10490         vec3_t center;
10491         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10492         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10493         {
10494                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10495                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10496         }
10497 }
10498
10499 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10500 {
10501         if (decalsystem->decals)
10502                 Mem_Free(decalsystem->decals);
10503         memset(decalsystem, 0, sizeof(*decalsystem));
10504 }
10505
10506 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)
10507 {
10508         tridecal_t *decal;
10509         tridecal_t *decals;
10510         int i;
10511
10512         // expand or initialize the system
10513         if (decalsystem->maxdecals <= decalsystem->numdecals)
10514         {
10515                 decalsystem_t old = *decalsystem;
10516                 qboolean useshortelements;
10517                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10518                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10519                 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)));
10520                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10521                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10522                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10523                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10524                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10525                 if (decalsystem->numdecals)
10526                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10527                 if (old.decals)
10528                         Mem_Free(old.decals);
10529                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10530                         decalsystem->element3i[i] = i;
10531                 if (useshortelements)
10532                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10533                                 decalsystem->element3s[i] = i;
10534         }
10535
10536         // grab a decal and search for another free slot for the next one
10537         decals = decalsystem->decals;
10538         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10539         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10540                 ;
10541         decalsystem->freedecal = i;
10542         if (decalsystem->numdecals <= i)
10543                 decalsystem->numdecals = i + 1;
10544
10545         // initialize the decal
10546         decal->lived = 0;
10547         decal->triangleindex = triangleindex;
10548         decal->surfaceindex = surfaceindex;
10549         decal->decalsequence = decalsequence;
10550         decal->color4f[0][0] = c0[0];
10551         decal->color4f[0][1] = c0[1];
10552         decal->color4f[0][2] = c0[2];
10553         decal->color4f[0][3] = 1;
10554         decal->color4f[1][0] = c1[0];
10555         decal->color4f[1][1] = c1[1];
10556         decal->color4f[1][2] = c1[2];
10557         decal->color4f[1][3] = 1;
10558         decal->color4f[2][0] = c2[0];
10559         decal->color4f[2][1] = c2[1];
10560         decal->color4f[2][2] = c2[2];
10561         decal->color4f[2][3] = 1;
10562         decal->vertex3f[0][0] = v0[0];
10563         decal->vertex3f[0][1] = v0[1];
10564         decal->vertex3f[0][2] = v0[2];
10565         decal->vertex3f[1][0] = v1[0];
10566         decal->vertex3f[1][1] = v1[1];
10567         decal->vertex3f[1][2] = v1[2];
10568         decal->vertex3f[2][0] = v2[0];
10569         decal->vertex3f[2][1] = v2[1];
10570         decal->vertex3f[2][2] = v2[2];
10571         decal->texcoord2f[0][0] = t0[0];
10572         decal->texcoord2f[0][1] = t0[1];
10573         decal->texcoord2f[1][0] = t1[0];
10574         decal->texcoord2f[1][1] = t1[1];
10575         decal->texcoord2f[2][0] = t2[0];
10576         decal->texcoord2f[2][1] = t2[1];
10577         TriangleNormal(v0, v1, v2, decal->plane);
10578         VectorNormalize(decal->plane);
10579         decal->plane[3] = DotProduct(v0, decal->plane);
10580 }
10581
10582 extern cvar_t cl_decals_bias;
10583 extern cvar_t cl_decals_models;
10584 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10585 // baseparms, parms, temps
10586 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)
10587 {
10588         int cornerindex;
10589         int index;
10590         float v[9][3];
10591         const float *vertex3f;
10592         const float *normal3f;
10593         int numpoints;
10594         float points[2][9][3];
10595         float temp[3];
10596         float tc[9][2];
10597         float f;
10598         float c[9][4];
10599         const int *e;
10600
10601         e = rsurface.modelelement3i + 3*triangleindex;
10602
10603         vertex3f = rsurface.modelvertex3f;
10604         normal3f = rsurface.modelnormal3f;
10605
10606         if (normal3f)
10607         {
10608                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10609                 {
10610                         index = 3*e[cornerindex];
10611                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10612                 }
10613         }
10614         else
10615         {
10616                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10617                 {
10618                         index = 3*e[cornerindex];
10619                         VectorCopy(vertex3f + index, v[cornerindex]);
10620                 }
10621         }
10622
10623         // cull backfaces
10624         //TriangleNormal(v[0], v[1], v[2], normal);
10625         //if (DotProduct(normal, localnormal) < 0.0f)
10626         //      continue;
10627         // clip by each of the box planes formed from the projection matrix
10628         // if anything survives, we emit the decal
10629         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]);
10630         if (numpoints < 3)
10631                 return;
10632         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]);
10633         if (numpoints < 3)
10634                 return;
10635         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]);
10636         if (numpoints < 3)
10637                 return;
10638         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]);
10639         if (numpoints < 3)
10640                 return;
10641         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]);
10642         if (numpoints < 3)
10643                 return;
10644         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]);
10645         if (numpoints < 3)
10646                 return;
10647         // some part of the triangle survived, so we have to accept it...
10648         if (dynamic)
10649         {
10650                 // dynamic always uses the original triangle
10651                 numpoints = 3;
10652                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10653                 {
10654                         index = 3*e[cornerindex];
10655                         VectorCopy(vertex3f + index, v[cornerindex]);
10656                 }
10657         }
10658         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10659         {
10660                 // convert vertex positions to texcoords
10661                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10662                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10663                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10664                 // calculate distance fade from the projection origin
10665                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10666                 f = bound(0.0f, f, 1.0f);
10667                 c[cornerindex][0] = r * f;
10668                 c[cornerindex][1] = g * f;
10669                 c[cornerindex][2] = b * f;
10670                 c[cornerindex][3] = 1.0f;
10671                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10672         }
10673         if (dynamic)
10674                 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);
10675         else
10676                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10677                         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);
10678 }
10679 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)
10680 {
10681         matrix4x4_t projection;
10682         decalsystem_t *decalsystem;
10683         qboolean dynamic;
10684         dp_model_t *model;
10685         const msurface_t *surface;
10686         const msurface_t *surfaces;
10687         const int *surfacelist;
10688         const texture_t *texture;
10689         int numtriangles;
10690         int numsurfacelist;
10691         int surfacelistindex;
10692         int surfaceindex;
10693         int triangleindex;
10694         float localorigin[3];
10695         float localnormal[3];
10696         float localmins[3];
10697         float localmaxs[3];
10698         float localsize;
10699         //float normal[3];
10700         float planes[6][4];
10701         float angles[3];
10702         bih_t *bih;
10703         int bih_triangles_count;
10704         int bih_triangles[256];
10705         int bih_surfaces[256];
10706
10707         decalsystem = &ent->decalsystem;
10708         model = ent->model;
10709         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10710         {
10711                 R_DecalSystem_Reset(&ent->decalsystem);
10712                 return;
10713         }
10714
10715         if (!model->brush.data_leafs && !cl_decals_models.integer)
10716         {
10717                 if (decalsystem->model)
10718                         R_DecalSystem_Reset(decalsystem);
10719                 return;
10720         }
10721
10722         if (decalsystem->model != model)
10723                 R_DecalSystem_Reset(decalsystem);
10724         decalsystem->model = model;
10725
10726         RSurf_ActiveModelEntity(ent, true, false, false);
10727
10728         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10729         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10730         VectorNormalize(localnormal);
10731         localsize = worldsize*rsurface.inversematrixscale;
10732         localmins[0] = localorigin[0] - localsize;
10733         localmins[1] = localorigin[1] - localsize;
10734         localmins[2] = localorigin[2] - localsize;
10735         localmaxs[0] = localorigin[0] + localsize;
10736         localmaxs[1] = localorigin[1] + localsize;
10737         localmaxs[2] = localorigin[2] + localsize;
10738
10739         //VectorCopy(localnormal, planes[4]);
10740         //VectorVectors(planes[4], planes[2], planes[0]);
10741         AnglesFromVectors(angles, localnormal, NULL, false);
10742         AngleVectors(angles, planes[0], planes[2], planes[4]);
10743         VectorNegate(planes[0], planes[1]);
10744         VectorNegate(planes[2], planes[3]);
10745         VectorNegate(planes[4], planes[5]);
10746         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10747         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10748         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10749         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10750         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10751         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10752
10753 #if 1
10754 // works
10755 {
10756         matrix4x4_t forwardprojection;
10757         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10758         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10759 }
10760 #else
10761 // broken
10762 {
10763         float projectionvector[4][3];
10764         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10765         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10766         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10767         projectionvector[0][0] = planes[0][0] * ilocalsize;
10768         projectionvector[0][1] = planes[1][0] * ilocalsize;
10769         projectionvector[0][2] = planes[2][0] * ilocalsize;
10770         projectionvector[1][0] = planes[0][1] * ilocalsize;
10771         projectionvector[1][1] = planes[1][1] * ilocalsize;
10772         projectionvector[1][2] = planes[2][1] * ilocalsize;
10773         projectionvector[2][0] = planes[0][2] * ilocalsize;
10774         projectionvector[2][1] = planes[1][2] * ilocalsize;
10775         projectionvector[2][2] = planes[2][2] * ilocalsize;
10776         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10777         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10778         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10779         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10780 }
10781 #endif
10782
10783         dynamic = model->surfmesh.isanimated;
10784         numsurfacelist = model->nummodelsurfaces;
10785         surfacelist = model->sortedmodelsurfaces;
10786         surfaces = model->data_surfaces;
10787
10788         bih = NULL;
10789         bih_triangles_count = -1;
10790         if(!dynamic)
10791         {
10792                 if(model->render_bih.numleafs)
10793                         bih = &model->render_bih;
10794                 else if(model->collision_bih.numleafs)
10795                         bih = &model->collision_bih;
10796         }
10797         if(bih)
10798                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10799         if(bih_triangles_count == 0)
10800                 return;
10801         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10802                 return;
10803         if(bih_triangles_count > 0)
10804         {
10805                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10806                 {
10807                         surfaceindex = bih_surfaces[triangleindex];
10808                         surface = surfaces + surfaceindex;
10809                         texture = surface->texture;
10810                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10811                                 continue;
10812                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10813                                 continue;
10814                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10815                 }
10816         }
10817         else
10818         {
10819                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10820                 {
10821                         surfaceindex = surfacelist[surfacelistindex];
10822                         surface = surfaces + surfaceindex;
10823                         // check cull box first because it rejects more than any other check
10824                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10825                                 continue;
10826                         // skip transparent surfaces
10827                         texture = surface->texture;
10828                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10829                                 continue;
10830                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10831                                 continue;
10832                         numtriangles = surface->num_triangles;
10833                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10834                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10835                 }
10836         }
10837 }
10838
10839 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10840 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)
10841 {
10842         int renderentityindex;
10843         float worldmins[3];
10844         float worldmaxs[3];
10845         entity_render_t *ent;
10846
10847         if (!cl_decals_newsystem.integer)
10848                 return;
10849
10850         worldmins[0] = worldorigin[0] - worldsize;
10851         worldmins[1] = worldorigin[1] - worldsize;
10852         worldmins[2] = worldorigin[2] - worldsize;
10853         worldmaxs[0] = worldorigin[0] + worldsize;
10854         worldmaxs[1] = worldorigin[1] + worldsize;
10855         worldmaxs[2] = worldorigin[2] + worldsize;
10856
10857         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10858
10859         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10860         {
10861                 ent = r_refdef.scene.entities[renderentityindex];
10862                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10863                         continue;
10864
10865                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10866         }
10867 }
10868
10869 typedef struct r_decalsystem_splatqueue_s
10870 {
10871         vec3_t worldorigin;
10872         vec3_t worldnormal;
10873         float color[4];
10874         float tcrange[4];
10875         float worldsize;
10876         int decalsequence;
10877 }
10878 r_decalsystem_splatqueue_t;
10879
10880 int r_decalsystem_numqueued = 0;
10881 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10882
10883 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)
10884 {
10885         r_decalsystem_splatqueue_t *queue;
10886
10887         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10888                 return;
10889
10890         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10891         VectorCopy(worldorigin, queue->worldorigin);
10892         VectorCopy(worldnormal, queue->worldnormal);
10893         Vector4Set(queue->color, r, g, b, a);
10894         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10895         queue->worldsize = worldsize;
10896         queue->decalsequence = cl.decalsequence++;
10897 }
10898
10899 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10900 {
10901         int i;
10902         r_decalsystem_splatqueue_t *queue;
10903
10904         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10905                 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);
10906         r_decalsystem_numqueued = 0;
10907 }
10908
10909 extern cvar_t cl_decals_max;
10910 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10911 {
10912         int i;
10913         decalsystem_t *decalsystem = &ent->decalsystem;
10914         int numdecals;
10915         int killsequence;
10916         tridecal_t *decal;
10917         float frametime;
10918         float lifetime;
10919
10920         if (!decalsystem->numdecals)
10921                 return;
10922
10923         if (r_showsurfaces.integer)
10924                 return;
10925
10926         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10927         {
10928                 R_DecalSystem_Reset(decalsystem);
10929                 return;
10930         }
10931
10932         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10933         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10934
10935         if (decalsystem->lastupdatetime)
10936                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10937         else
10938                 frametime = 0;
10939         decalsystem->lastupdatetime = r_refdef.scene.time;
10940         decal = decalsystem->decals;
10941         numdecals = decalsystem->numdecals;
10942
10943         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10944         {
10945                 if (decal->color4f[0][3])
10946                 {
10947                         decal->lived += frametime;
10948                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10949                         {
10950                                 memset(decal, 0, sizeof(*decal));
10951                                 if (decalsystem->freedecal > i)
10952                                         decalsystem->freedecal = i;
10953                         }
10954                 }
10955         }
10956         decal = decalsystem->decals;
10957         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10958                 numdecals--;
10959
10960         // collapse the array by shuffling the tail decals into the gaps
10961         for (;;)
10962         {
10963                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10964                         decalsystem->freedecal++;
10965                 if (decalsystem->freedecal == numdecals)
10966                         break;
10967                 decal[decalsystem->freedecal] = decal[--numdecals];
10968         }
10969
10970         decalsystem->numdecals = numdecals;
10971
10972         if (numdecals <= 0)
10973         {
10974                 // if there are no decals left, reset decalsystem
10975                 R_DecalSystem_Reset(decalsystem);
10976         }
10977 }
10978
10979 extern skinframe_t *decalskinframe;
10980 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10981 {
10982         int i;
10983         decalsystem_t *decalsystem = &ent->decalsystem;
10984         int numdecals;
10985         tridecal_t *decal;
10986         float faderate;
10987         float alpha;
10988         float *v3f;
10989         float *c4f;
10990         float *t2f;
10991         const int *e;
10992         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10993         int numtris = 0;
10994
10995         numdecals = decalsystem->numdecals;
10996         if (!numdecals)
10997                 return;
10998
10999         if (r_showsurfaces.integer)
11000                 return;
11001
11002         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11003         {
11004                 R_DecalSystem_Reset(decalsystem);
11005                 return;
11006         }
11007
11008         // if the model is static it doesn't matter what value we give for
11009         // wantnormals and wanttangents, so this logic uses only rules applicable
11010         // to a model, knowing that they are meaningless otherwise
11011         if (ent == r_refdef.scene.worldentity)
11012                 RSurf_ActiveWorldEntity();
11013         else
11014                 RSurf_ActiveModelEntity(ent, false, false, false);
11015
11016         decalsystem->lastupdatetime = r_refdef.scene.time;
11017         decal = decalsystem->decals;
11018
11019         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11020
11021         // update vertex positions for animated models
11022         v3f = decalsystem->vertex3f;
11023         c4f = decalsystem->color4f;
11024         t2f = decalsystem->texcoord2f;
11025         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11026         {
11027                 if (!decal->color4f[0][3])
11028                         continue;
11029
11030                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11031                         continue;
11032
11033                 // skip backfaces
11034                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11035                         continue;
11036
11037                 // update color values for fading decals
11038                 if (decal->lived >= cl_decals_time.value)
11039                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11040                 else
11041                         alpha = 1.0f;
11042
11043                 c4f[ 0] = decal->color4f[0][0] * alpha;
11044                 c4f[ 1] = decal->color4f[0][1] * alpha;
11045                 c4f[ 2] = decal->color4f[0][2] * alpha;
11046                 c4f[ 3] = 1;
11047                 c4f[ 4] = decal->color4f[1][0] * alpha;
11048                 c4f[ 5] = decal->color4f[1][1] * alpha;
11049                 c4f[ 6] = decal->color4f[1][2] * alpha;
11050                 c4f[ 7] = 1;
11051                 c4f[ 8] = decal->color4f[2][0] * alpha;
11052                 c4f[ 9] = decal->color4f[2][1] * alpha;
11053                 c4f[10] = decal->color4f[2][2] * alpha;
11054                 c4f[11] = 1;
11055
11056                 t2f[0] = decal->texcoord2f[0][0];
11057                 t2f[1] = decal->texcoord2f[0][1];
11058                 t2f[2] = decal->texcoord2f[1][0];
11059                 t2f[3] = decal->texcoord2f[1][1];
11060                 t2f[4] = decal->texcoord2f[2][0];
11061                 t2f[5] = decal->texcoord2f[2][1];
11062
11063                 // update vertex positions for animated models
11064                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11065                 {
11066                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11067                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11068                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11069                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11070                 }
11071                 else
11072                 {
11073                         VectorCopy(decal->vertex3f[0], v3f);
11074                         VectorCopy(decal->vertex3f[1], v3f + 3);
11075                         VectorCopy(decal->vertex3f[2], v3f + 6);
11076                 }
11077
11078                 if (r_refdef.fogenabled)
11079                 {
11080                         alpha = RSurf_FogVertex(v3f);
11081                         VectorScale(c4f, alpha, c4f);
11082                         alpha = RSurf_FogVertex(v3f + 3);
11083                         VectorScale(c4f + 4, alpha, c4f + 4);
11084                         alpha = RSurf_FogVertex(v3f + 6);
11085                         VectorScale(c4f + 8, alpha, c4f + 8);
11086                 }
11087
11088                 v3f += 9;
11089                 c4f += 12;
11090                 t2f += 6;
11091                 numtris++;
11092         }
11093
11094         if (numtris > 0)
11095         {
11096                 r_refdef.stats.drawndecals += numtris;
11097
11098                 // now render the decals all at once
11099                 // (this assumes they all use one particle font texture!)
11100                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11101 //              R_Mesh_ResetTextureState();
11102                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11103                 GL_DepthMask(false);
11104                 GL_DepthRange(0, 1);
11105                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11106                 GL_DepthTest(true);
11107                 GL_CullFace(GL_NONE);
11108                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11109                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11110                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11111         }
11112 }
11113
11114 static void R_DrawModelDecals(void)
11115 {
11116         int i, numdecals;
11117
11118         // fade faster when there are too many decals
11119         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11120         for (i = 0;i < r_refdef.scene.numentities;i++)
11121                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11122
11123         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11124         for (i = 0;i < r_refdef.scene.numentities;i++)
11125                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11126                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11127
11128         R_DecalSystem_ApplySplatEntitiesQueue();
11129
11130         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11131         for (i = 0;i < r_refdef.scene.numentities;i++)
11132                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11133
11134         r_refdef.stats.totaldecals += numdecals;
11135
11136         if (r_showsurfaces.integer)
11137                 return;
11138
11139         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11140
11141         for (i = 0;i < r_refdef.scene.numentities;i++)
11142         {
11143                 if (!r_refdef.viewcache.entityvisible[i])
11144                         continue;
11145                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11146                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11147         }
11148 }
11149
11150 extern cvar_t mod_collision_bih;
11151 void R_DrawDebugModel(void)
11152 {
11153         entity_render_t *ent = rsurface.entity;
11154         int i, j, k, l, flagsmask;
11155         const msurface_t *surface;
11156         dp_model_t *model = ent->model;
11157         vec3_t v;
11158
11159         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11160                 return;
11161
11162         if (r_showoverdraw.value > 0)
11163         {
11164                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11165                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11166                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11167                 GL_DepthTest(false);
11168                 GL_DepthMask(false);
11169                 GL_DepthRange(0, 1);
11170                 GL_BlendFunc(GL_ONE, GL_ONE);
11171                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11172                 {
11173                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11174                                 continue;
11175                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11176                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11177                         {
11178                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11179                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11180                                 if (!rsurface.texture->currentlayers->depthmask)
11181                                         GL_Color(c, 0, 0, 1.0f);
11182                                 else if (ent == r_refdef.scene.worldentity)
11183                                         GL_Color(c, c, c, 1.0f);
11184                                 else
11185                                         GL_Color(0, c, 0, 1.0f);
11186                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11187                                 RSurf_DrawBatch();
11188                         }
11189                 }
11190                 rsurface.texture = NULL;
11191         }
11192
11193         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11194
11195 //      R_Mesh_ResetTextureState();
11196         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11197         GL_DepthRange(0, 1);
11198         GL_DepthTest(!r_showdisabledepthtest.integer);
11199         GL_DepthMask(false);
11200         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11201
11202         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11203         {
11204                 int triangleindex;
11205                 int bihleafindex;
11206                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11207                 const q3mbrush_t *brush;
11208                 const bih_t *bih = &model->collision_bih;
11209                 const bih_leaf_t *bihleaf;
11210                 float vertex3f[3][3];
11211                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11212                 cullbox = false;
11213                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11214                 {
11215                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11216                                 continue;
11217                         switch (bihleaf->type)
11218                         {
11219                         case BIH_BRUSH:
11220                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11221                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11222                                 {
11223                                         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);
11224                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11225                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11226                                 }
11227                                 break;
11228                         case BIH_COLLISIONTRIANGLE:
11229                                 triangleindex = bihleaf->itemindex;
11230                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11231                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11232                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11233                                 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);
11234                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11235                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11236                                 break;
11237                         case BIH_RENDERTRIANGLE:
11238                                 triangleindex = bihleaf->itemindex;
11239                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11240                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11241                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11242                                 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);
11243                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11244                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11245                                 break;
11246                         }
11247                 }
11248         }
11249
11250         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11251
11252         if (r_showtris.integer && qglPolygonMode)
11253         {
11254                 if (r_showdisabledepthtest.integer)
11255                 {
11256                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11257                         GL_DepthMask(false);
11258                 }
11259                 else
11260                 {
11261                         GL_BlendFunc(GL_ONE, GL_ZERO);
11262                         GL_DepthMask(true);
11263                 }
11264                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11265                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11266                 {
11267                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11268                                 continue;
11269                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11270                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11271                         {
11272                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11273                                 if (!rsurface.texture->currentlayers->depthmask)
11274                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11275                                 else if (ent == r_refdef.scene.worldentity)
11276                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11277                                 else
11278                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11279                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11280                                 RSurf_DrawBatch();
11281                         }
11282                 }
11283                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11284                 rsurface.texture = NULL;
11285         }
11286
11287         if (r_shownormals.value != 0 && qglBegin)
11288         {
11289                 if (r_showdisabledepthtest.integer)
11290                 {
11291                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11292                         GL_DepthMask(false);
11293                 }
11294                 else
11295                 {
11296                         GL_BlendFunc(GL_ONE, GL_ZERO);
11297                         GL_DepthMask(true);
11298                 }
11299                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11300                 {
11301                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11302                                 continue;
11303                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11304                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11305                         {
11306                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11307                                 qglBegin(GL_LINES);
11308                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11309                                 {
11310                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11311                                         {
11312                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11313                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11314                                                 qglVertex3f(v[0], v[1], v[2]);
11315                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11316                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11317                                                 qglVertex3f(v[0], v[1], v[2]);
11318                                         }
11319                                 }
11320                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11321                                 {
11322                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11323                                         {
11324                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11325                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11326                                                 qglVertex3f(v[0], v[1], v[2]);
11327                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11328                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11329                                                 qglVertex3f(v[0], v[1], v[2]);
11330                                         }
11331                                 }
11332                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11333                                 {
11334                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11335                                         {
11336                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11337                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11338                                                 qglVertex3f(v[0], v[1], v[2]);
11339                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11340                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11341                                                 qglVertex3f(v[0], v[1], v[2]);
11342                                         }
11343                                 }
11344                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11345                                 {
11346                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11347                                         {
11348                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11349                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11350                                                 qglVertex3f(v[0], v[1], v[2]);
11351                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11352                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11353                                                 qglVertex3f(v[0], v[1], v[2]);
11354                                         }
11355                                 }
11356                                 qglEnd();
11357                                 CHECKGLERROR
11358                         }
11359                 }
11360                 rsurface.texture = NULL;
11361         }
11362 }
11363
11364 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11365 int r_maxsurfacelist = 0;
11366 const msurface_t **r_surfacelist = NULL;
11367 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11368 {
11369         int i, j, endj, flagsmask;
11370         dp_model_t *model = r_refdef.scene.worldmodel;
11371         msurface_t *surfaces;
11372         unsigned char *update;
11373         int numsurfacelist = 0;
11374         if (model == NULL)
11375                 return;
11376
11377         if (r_maxsurfacelist < model->num_surfaces)
11378         {
11379                 r_maxsurfacelist = model->num_surfaces;
11380                 if (r_surfacelist)
11381                         Mem_Free((msurface_t**)r_surfacelist);
11382                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11383         }
11384
11385         RSurf_ActiveWorldEntity();
11386
11387         surfaces = model->data_surfaces;
11388         update = model->brushq1.lightmapupdateflags;
11389
11390         // update light styles on this submodel
11391         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11392         {
11393                 model_brush_lightstyleinfo_t *style;
11394                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11395                 {
11396                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11397                         {
11398                                 int *list = style->surfacelist;
11399                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11400                                 for (j = 0;j < style->numsurfaces;j++)
11401                                         update[list[j]] = true;
11402                         }
11403                 }
11404         }
11405
11406         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11407
11408         if (debug)
11409         {
11410                 R_DrawDebugModel();
11411                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11412                 return;
11413         }
11414
11415         rsurface.lightmaptexture = NULL;
11416         rsurface.deluxemaptexture = NULL;
11417         rsurface.uselightmaptexture = false;
11418         rsurface.texture = NULL;
11419         rsurface.rtlight = NULL;
11420         numsurfacelist = 0;
11421         // add visible surfaces to draw list
11422         for (i = 0;i < model->nummodelsurfaces;i++)
11423         {
11424                 j = model->sortedmodelsurfaces[i];
11425                 if (r_refdef.viewcache.world_surfacevisible[j])
11426                         r_surfacelist[numsurfacelist++] = surfaces + j;
11427         }
11428         // update lightmaps if needed
11429         if (model->brushq1.firstrender)
11430         {
11431                 model->brushq1.firstrender = false;
11432                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11433                         if (update[j])
11434                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11435         }
11436         else if (update)
11437         {
11438                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11439                         if (r_refdef.viewcache.world_surfacevisible[j])
11440                                 if (update[j])
11441                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11442         }
11443         // don't do anything if there were no surfaces
11444         if (!numsurfacelist)
11445         {
11446                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11447                 return;
11448         }
11449         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11450
11451         // add to stats if desired
11452         if (r_speeds.integer && !skysurfaces && !depthonly)
11453         {
11454                 r_refdef.stats.world_surfaces += numsurfacelist;
11455                 for (j = 0;j < numsurfacelist;j++)
11456                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11457         }
11458
11459         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11460 }
11461
11462 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11463 {
11464         int i, j, endj, flagsmask;
11465         dp_model_t *model = ent->model;
11466         msurface_t *surfaces;
11467         unsigned char *update;
11468         int numsurfacelist = 0;
11469         if (model == NULL)
11470                 return;
11471
11472         if (r_maxsurfacelist < model->num_surfaces)
11473         {
11474                 r_maxsurfacelist = model->num_surfaces;
11475                 if (r_surfacelist)
11476                         Mem_Free((msurface_t **)r_surfacelist);
11477                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11478         }
11479
11480         // if the model is static it doesn't matter what value we give for
11481         // wantnormals and wanttangents, so this logic uses only rules applicable
11482         // to a model, knowing that they are meaningless otherwise
11483         if (ent == r_refdef.scene.worldentity)
11484                 RSurf_ActiveWorldEntity();
11485         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11486                 RSurf_ActiveModelEntity(ent, false, false, false);
11487         else if (prepass)
11488                 RSurf_ActiveModelEntity(ent, true, true, true);
11489         else if (depthonly)
11490         {
11491                 switch (vid.renderpath)
11492                 {
11493                 case RENDERPATH_GL20:
11494                 case RENDERPATH_D3D9:
11495                 case RENDERPATH_D3D10:
11496                 case RENDERPATH_D3D11:
11497                 case RENDERPATH_SOFT:
11498                 case RENDERPATH_GLES2:
11499                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11500                         break;
11501                 case RENDERPATH_GL11:
11502                 case RENDERPATH_GL13:
11503                 case RENDERPATH_GLES1:
11504                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11505                         break;
11506                 }
11507         }
11508         else
11509         {
11510                 switch (vid.renderpath)
11511                 {
11512                 case RENDERPATH_GL20:
11513                 case RENDERPATH_D3D9:
11514                 case RENDERPATH_D3D10:
11515                 case RENDERPATH_D3D11:
11516                 case RENDERPATH_SOFT:
11517                 case RENDERPATH_GLES2:
11518                         RSurf_ActiveModelEntity(ent, true, true, false);
11519                         break;
11520                 case RENDERPATH_GL11:
11521                 case RENDERPATH_GL13:
11522                 case RENDERPATH_GLES1:
11523                         RSurf_ActiveModelEntity(ent, true, false, false);
11524                         break;
11525                 }
11526         }
11527
11528         surfaces = model->data_surfaces;
11529         update = model->brushq1.lightmapupdateflags;
11530
11531         // update light styles
11532         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11533         {
11534                 model_brush_lightstyleinfo_t *style;
11535                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11536                 {
11537                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11538                         {
11539                                 int *list = style->surfacelist;
11540                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11541                                 for (j = 0;j < style->numsurfaces;j++)
11542                                         update[list[j]] = true;
11543                         }
11544                 }
11545         }
11546
11547         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11548
11549         if (debug)
11550         {
11551                 R_DrawDebugModel();
11552                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11553                 return;
11554         }
11555
11556         rsurface.lightmaptexture = NULL;
11557         rsurface.deluxemaptexture = NULL;
11558         rsurface.uselightmaptexture = false;
11559         rsurface.texture = NULL;
11560         rsurface.rtlight = NULL;
11561         numsurfacelist = 0;
11562         // add visible surfaces to draw list
11563         for (i = 0;i < model->nummodelsurfaces;i++)
11564                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11565         // don't do anything if there were no surfaces
11566         if (!numsurfacelist)
11567         {
11568                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11569                 return;
11570         }
11571         // update lightmaps if needed
11572         if (update)
11573         {
11574                 int updated = 0;
11575                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11576                 {
11577                         if (update[j])
11578                         {
11579                                 updated++;
11580                                 R_BuildLightMap(ent, surfaces + j);
11581                         }
11582                 }
11583         }
11584         if (update)
11585                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11586                         if (update[j])
11587                                 R_BuildLightMap(ent, surfaces + j);
11588         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11589
11590         // add to stats if desired
11591         if (r_speeds.integer && !skysurfaces && !depthonly)
11592         {
11593                 r_refdef.stats.entities_surfaces += numsurfacelist;
11594                 for (j = 0;j < numsurfacelist;j++)
11595                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11596         }
11597
11598         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11599 }
11600
11601 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11602 {
11603         static texture_t texture;
11604         static msurface_t surface;
11605         const msurface_t *surfacelist = &surface;
11606
11607         // fake enough texture and surface state to render this geometry
11608
11609         texture.update_lastrenderframe = -1; // regenerate this texture
11610         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11611         texture.currentskinframe = skinframe;
11612         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11613         texture.offsetmapping = OFFSETMAPPING_OFF;
11614         texture.offsetscale = 1;
11615         texture.specularscalemod = 1;
11616         texture.specularpowermod = 1;
11617
11618         surface.texture = &texture;
11619         surface.num_triangles = numtriangles;
11620         surface.num_firsttriangle = firsttriangle;
11621         surface.num_vertices = numvertices;
11622         surface.num_firstvertex = firstvertex;
11623
11624         // now render it
11625         rsurface.texture = R_GetCurrentTexture(surface.texture);
11626         rsurface.lightmaptexture = NULL;
11627         rsurface.deluxemaptexture = NULL;
11628         rsurface.uselightmaptexture = false;
11629         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11630 }
11631
11632 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)
11633 {
11634         static msurface_t surface;
11635         const msurface_t *surfacelist = &surface;
11636
11637         // fake enough texture and surface state to render this geometry
11638         surface.texture = texture;
11639         surface.num_triangles = numtriangles;
11640         surface.num_firsttriangle = firsttriangle;
11641         surface.num_vertices = numvertices;
11642         surface.num_firstvertex = firstvertex;
11643
11644         // now render it
11645         rsurface.texture = R_GetCurrentTexture(surface.texture);
11646         rsurface.lightmaptexture = NULL;
11647         rsurface.deluxemaptexture = NULL;
11648         rsurface.uselightmaptexture = false;
11649         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11650 }