]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
8722db4c23b04be18dd933133aaa3ed309a2a6df
[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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
99
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
103
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
126
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
135
136 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)"};
137 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"};
138
139 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
144 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
145 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
146
147 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
148 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
149 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
150
151 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"};
152 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"};
153 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
154 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
155 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"};
156 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)"};
157 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)"};
158 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
159
160 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)"};
161 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
164 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)"};
165 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)"};
166 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
183
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
188
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
196
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 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)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
207
208 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"};
209
210 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"};
211
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
216 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
217 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
218 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
219 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
220 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
221 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
222 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
226
227 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."};
228
229 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)"};
230
231 extern cvar_t v_glslgamma;
232
233 extern qboolean v_flipped_state;
234
235 static struct r_bloomstate_s
236 {
237         qboolean enabled;
238         qboolean hdr;
239
240         int bloomwidth, bloomheight;
241
242         textype_t texturetype;
243         int viewfbo; // used to check if r_viewfbo cvar has changed
244
245         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
246         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
247         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
248
249         int screentexturewidth, screentextureheight;
250         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
251
252         int bloomtexturewidth, bloomtextureheight;
253         rtexture_t *texture_bloom;
254
255         // arrays for rendering the screen passes
256         float screentexcoord2f[8];
257         float bloomtexcoord2f[8];
258         float offsettexcoord2f[8];
259
260         r_viewport_t viewport;
261 }
262 r_bloomstate;
263
264 r_waterstate_t r_waterstate;
265
266 /// shadow volume bsp struct with automatically growing nodes buffer
267 svbsp_t r_svbsp;
268
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
282
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
285 {
286         char basename[64];
287         rtexture_t *texture;
288 }
289 cubemapinfo_t;
290
291 int r_texture_numcubemaps;
292 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
293
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
297
298 typedef struct r_qwskincache_s
299 {
300         char name[MAX_QPATH];
301         skinframe_t *skinframe;
302 }
303 r_qwskincache_t;
304
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
307
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
312 {
313         0, 0, 0,
314         1, 0, 0,
315         1, 1, 0,
316         0, 1, 0
317 };
318 const float r_d3dscreenvertex3f[12] =
319 {
320         0, 1, 0,
321         1, 1, 0,
322         1, 0, 0,
323         0, 0, 0
324 };
325
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = in[0] * r;
332                 out[1] = in[1] * g;
333                 out[2] = in[2] * b;
334                 out[3] = in[3];
335                 in += 4;
336                 out += 4;
337         }
338 }
339
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = r;
346                 out[1] = g;
347                 out[2] = b;
348                 out[3] = a;
349                 out += 4;
350         }
351 }
352
353 // FIXME: move this to client?
354 void FOG_clear(void)
355 {
356         if (gamemode == GAME_NEHAHRA)
357         {
358                 Cvar_Set("gl_fogenable", "0");
359                 Cvar_Set("gl_fogdensity", "0.2");
360                 Cvar_Set("gl_fogred", "0.3");
361                 Cvar_Set("gl_foggreen", "0.3");
362                 Cvar_Set("gl_fogblue", "0.3");
363         }
364         r_refdef.fog_density = 0;
365         r_refdef.fog_red = 0;
366         r_refdef.fog_green = 0;
367         r_refdef.fog_blue = 0;
368         r_refdef.fog_alpha = 1;
369         r_refdef.fog_start = 0;
370         r_refdef.fog_end = 16384;
371         r_refdef.fog_height = 1<<30;
372         r_refdef.fog_fadedepth = 128;
373         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
374 }
375
376 static void R_BuildBlankTextures(void)
377 {
378         unsigned char data[4];
379         data[2] = 128; // normal X
380         data[1] = 128; // normal Y
381         data[0] = 255; // normal Z
382         data[3] = 128; // height
383         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 255;
385         data[1] = 255;
386         data[2] = 255;
387         data[3] = 255;
388         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 128;
390         data[1] = 128;
391         data[2] = 128;
392         data[3] = 255;
393         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394         data[0] = 0;
395         data[1] = 0;
396         data[2] = 0;
397         data[3] = 255;
398         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNoTexture(void)
402 {
403         int x, y;
404         unsigned char pix[16][16][4];
405         // this makes a light grey/dark grey checkerboard texture
406         for (y = 0;y < 16;y++)
407         {
408                 for (x = 0;x < 16;x++)
409                 {
410                         if ((y < 8) ^ (x < 8))
411                         {
412                                 pix[y][x][0] = 128;
413                                 pix[y][x][1] = 128;
414                                 pix[y][x][2] = 128;
415                                 pix[y][x][3] = 255;
416                         }
417                         else
418                         {
419                                 pix[y][x][0] = 64;
420                                 pix[y][x][1] = 64;
421                                 pix[y][x][2] = 64;
422                                 pix[y][x][3] = 255;
423                         }
424                 }
425         }
426         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildWhiteCube(void)
430 {
431         unsigned char data[6*1*1*4];
432         memset(data, 255, sizeof(data));
433         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
434 }
435
436 static void R_BuildNormalizationCube(void)
437 {
438         int x, y, side;
439         vec3_t v;
440         vec_t s, t, intensity;
441 #define NORMSIZE 64
442         unsigned char *data;
443         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444         for (side = 0;side < 6;side++)
445         {
446                 for (y = 0;y < NORMSIZE;y++)
447                 {
448                         for (x = 0;x < NORMSIZE;x++)
449                         {
450                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
452                                 switch(side)
453                                 {
454                                 default:
455                                 case 0:
456                                         v[0] = 1;
457                                         v[1] = -t;
458                                         v[2] = -s;
459                                         break;
460                                 case 1:
461                                         v[0] = -1;
462                                         v[1] = -t;
463                                         v[2] = s;
464                                         break;
465                                 case 2:
466                                         v[0] = s;
467                                         v[1] = 1;
468                                         v[2] = t;
469                                         break;
470                                 case 3:
471                                         v[0] = s;
472                                         v[1] = -1;
473                                         v[2] = -t;
474                                         break;
475                                 case 4:
476                                         v[0] = s;
477                                         v[1] = -t;
478                                         v[2] = 1;
479                                         break;
480                                 case 5:
481                                         v[0] = -s;
482                                         v[1] = -t;
483                                         v[2] = -1;
484                                         break;
485                                 }
486                                 intensity = 127.0f / sqrt(DotProduct(v, v));
487                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490                                 data[((side*64+y)*64+x)*4+3] = 255;
491                         }
492                 }
493         }
494         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
495         Mem_Free(data);
496 }
497
498 static void R_BuildFogTexture(void)
499 {
500         int x, b;
501 #define FOGWIDTH 256
502         unsigned char data1[FOGWIDTH][4];
503         //unsigned char data2[FOGWIDTH][4];
504         double d, r, alpha;
505
506         r_refdef.fogmasktable_start = r_refdef.fog_start;
507         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508         r_refdef.fogmasktable_range = r_refdef.fogrange;
509         r_refdef.fogmasktable_density = r_refdef.fog_density;
510
511         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
513         {
514                 d = (x * r - r_refdef.fogmasktable_start);
515                 if(developer_extra.integer)
516                         Con_DPrintf("%f ", d);
517                 d = max(0, d);
518                 if (r_fog_exp2.integer)
519                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
520                 else
521                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522                 if(developer_extra.integer)
523                         Con_DPrintf(" : %f ", alpha);
524                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525                 if(developer_extra.integer)
526                         Con_DPrintf(" = %f\n", alpha);
527                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
528         }
529
530         for (x = 0;x < FOGWIDTH;x++)
531         {
532                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533                 data1[x][0] = b;
534                 data1[x][1] = b;
535                 data1[x][2] = b;
536                 data1[x][3] = 255;
537                 //data2[x][0] = 255 - b;
538                 //data2[x][1] = 255 - b;
539                 //data2[x][2] = 255 - b;
540                 //data2[x][3] = 255;
541         }
542         if (r_texture_fogattenuation)
543         {
544                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
546         }
547         else
548         {
549                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
551         }
552 }
553
554 static void R_BuildFogHeightTexture(void)
555 {
556         unsigned char *inpixels;
557         int size;
558         int x;
559         int y;
560         int j;
561         float c[4];
562         float f;
563         inpixels = NULL;
564         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565         if (r_refdef.fogheighttexturename[0])
566                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
567         if (!inpixels)
568         {
569                 r_refdef.fog_height_tablesize = 0;
570                 if (r_texture_fogheighttexture)
571                         R_FreeTexture(r_texture_fogheighttexture);
572                 r_texture_fogheighttexture = NULL;
573                 if (r_refdef.fog_height_table2d)
574                         Mem_Free(r_refdef.fog_height_table2d);
575                 r_refdef.fog_height_table2d = NULL;
576                 if (r_refdef.fog_height_table1d)
577                         Mem_Free(r_refdef.fog_height_table1d);
578                 r_refdef.fog_height_table1d = NULL;
579                 return;
580         }
581         size = image_width;
582         r_refdef.fog_height_tablesize = size;
583         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
586         Mem_Free(inpixels);
587         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
588         // average fog color table accounting for every fog layer between a point
589         // and the camera.  (Note: attenuation is handled separately!)
590         for (y = 0;y < size;y++)
591         {
592                 for (x = 0;x < size;x++)
593                 {
594                         Vector4Clear(c);
595                         f = 0;
596                         if (x < y)
597                         {
598                                 for (j = x;j <= y;j++)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         else
605                         {
606                                 for (j = x;j >= y;j--)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         f = 1.0f / f;
613                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
617                 }
618         }
619         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
620 }
621
622 //=======================================================================================================================================================
623
624 static const char *builtinshaderstring =
625 #include "shader_glsl.h"
626 ;
627
628 const char *builtinhlslshaderstring =
629 #include "shader_hlsl.h"
630 ;
631
632 char *glslshaderstring = NULL;
633 char *hlslshaderstring = NULL;
634
635 //=======================================================================================================================================================
636
637 typedef struct shaderpermutationinfo_s
638 {
639         const char *pretext;
640         const char *name;
641 }
642 shaderpermutationinfo_t;
643
644 typedef struct shadermodeinfo_s
645 {
646         const char *vertexfilename;
647         const char *geometryfilename;
648         const char *fragmentfilename;
649         const char *pretext;
650         const char *name;
651 }
652 shadermodeinfo_t;
653
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
656 {
657         {"#define USEDIFFUSE\n", " diffuse"},
658         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
659         {"#define USEVIEWTINT\n", " viewtint"},
660         {"#define USECOLORMAPPING\n", " colormapping"},
661         {"#define USESATURATION\n", " saturation"},
662         {"#define USEFOGINSIDE\n", " foginside"},
663         {"#define USEFOGOUTSIDE\n", " fogoutside"},
664         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
665         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
666         {"#define USEGAMMARAMPS\n", " gammaramps"},
667         {"#define USECUBEFILTER\n", " cubefilter"},
668         {"#define USEGLOW\n", " glow"},
669         {"#define USEBLOOM\n", " bloom"},
670         {"#define USESPECULAR\n", " specular"},
671         {"#define USEPOSTPROCESSING\n", " postprocessing"},
672         {"#define USEREFLECTION\n", " reflection"},
673         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
674         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
675         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
676         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
677         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
678         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
679         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
680         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
681         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
682         {"#define USEALPHAKILL\n", " alphakill"},
683         {"#define USEREFLECTCUBE\n", " reflectcube"},
684         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
685         {"#define USEBOUNCEGRID\n", " bouncegrid"},
686         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
687 };
688
689 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
690 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
691 {
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
694         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 };
729
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
732 {
733         /// hash lookup data
734         struct r_glsl_permutation_s *hashnext;
735         unsigned int mode;
736         unsigned int permutation;
737
738         /// indicates if we have tried compiling this permutation already
739         qboolean compiled;
740         /// 0 if compilation failed
741         int program;
742         // texture units assigned to each detected uniform
743         int tex_Texture_First;
744         int tex_Texture_Second;
745         int tex_Texture_GammaRamps;
746         int tex_Texture_Normal;
747         int tex_Texture_Color;
748         int tex_Texture_Gloss;
749         int tex_Texture_Glow;
750         int tex_Texture_SecondaryNormal;
751         int tex_Texture_SecondaryColor;
752         int tex_Texture_SecondaryGloss;
753         int tex_Texture_SecondaryGlow;
754         int tex_Texture_Pants;
755         int tex_Texture_Shirt;
756         int tex_Texture_FogHeightTexture;
757         int tex_Texture_FogMask;
758         int tex_Texture_Lightmap;
759         int tex_Texture_Deluxemap;
760         int tex_Texture_Attenuation;
761         int tex_Texture_Cube;
762         int tex_Texture_Refraction;
763         int tex_Texture_Reflection;
764         int tex_Texture_ShadowMap2D;
765         int tex_Texture_CubeProjection;
766         int tex_Texture_ScreenDepth;
767         int tex_Texture_ScreenNormalMap;
768         int tex_Texture_ScreenDiffuse;
769         int tex_Texture_ScreenSpecular;
770         int tex_Texture_ReflectMask;
771         int tex_Texture_ReflectCube;
772         int tex_Texture_BounceGrid;
773         /// locations of detected uniforms in program object, or -1 if not found
774         int loc_Texture_First;
775         int loc_Texture_Second;
776         int loc_Texture_GammaRamps;
777         int loc_Texture_Normal;
778         int loc_Texture_Color;
779         int loc_Texture_Gloss;
780         int loc_Texture_Glow;
781         int loc_Texture_SecondaryNormal;
782         int loc_Texture_SecondaryColor;
783         int loc_Texture_SecondaryGloss;
784         int loc_Texture_SecondaryGlow;
785         int loc_Texture_Pants;
786         int loc_Texture_Shirt;
787         int loc_Texture_FogHeightTexture;
788         int loc_Texture_FogMask;
789         int loc_Texture_Lightmap;
790         int loc_Texture_Deluxemap;
791         int loc_Texture_Attenuation;
792         int loc_Texture_Cube;
793         int loc_Texture_Refraction;
794         int loc_Texture_Reflection;
795         int loc_Texture_ShadowMap2D;
796         int loc_Texture_CubeProjection;
797         int loc_Texture_ScreenDepth;
798         int loc_Texture_ScreenNormalMap;
799         int loc_Texture_ScreenDiffuse;
800         int loc_Texture_ScreenSpecular;
801         int loc_Texture_ReflectMask;
802         int loc_Texture_ReflectCube;
803         int loc_Texture_BounceGrid;
804         int loc_Alpha;
805         int loc_BloomBlur_Parameters;
806         int loc_ClientTime;
807         int loc_Color_Ambient;
808         int loc_Color_Diffuse;
809         int loc_Color_Specular;
810         int loc_Color_Glow;
811         int loc_Color_Pants;
812         int loc_Color_Shirt;
813         int loc_DeferredColor_Ambient;
814         int loc_DeferredColor_Diffuse;
815         int loc_DeferredColor_Specular;
816         int loc_DeferredMod_Diffuse;
817         int loc_DeferredMod_Specular;
818         int loc_DistortScaleRefractReflect;
819         int loc_EyePosition;
820         int loc_FogColor;
821         int loc_FogHeightFade;
822         int loc_FogPlane;
823         int loc_FogPlaneViewDist;
824         int loc_FogRangeRecip;
825         int loc_LightColor;
826         int loc_LightDir;
827         int loc_LightPosition;
828         int loc_OffsetMapping_ScaleSteps;
829         int loc_PixelSize;
830         int loc_ReflectColor;
831         int loc_ReflectFactor;
832         int loc_ReflectOffset;
833         int loc_RefractColor;
834         int loc_Saturation;
835         int loc_ScreenCenterRefractReflect;
836         int loc_ScreenScaleRefractReflect;
837         int loc_ScreenToDepth;
838         int loc_ShadowMap_Parameters;
839         int loc_ShadowMap_TextureScale;
840         int loc_SpecularPower;
841         int loc_UserVec1;
842         int loc_UserVec2;
843         int loc_UserVec3;
844         int loc_UserVec4;
845         int loc_ViewTintColor;
846         int loc_ViewToLight;
847         int loc_ModelToLight;
848         int loc_TexMatrix;
849         int loc_BackgroundTexMatrix;
850         int loc_ModelViewProjectionMatrix;
851         int loc_ModelViewMatrix;
852         int loc_PixelToScreenTexCoord;
853         int loc_ModelToReflectCube;
854         int loc_ShadowMapMatrix;
855         int loc_BloomColorSubtract;
856         int loc_NormalmapScrollBlend;
857         int loc_BounceGridMatrix;
858         int loc_BounceGridIntensity;
859 }
860 r_glsl_permutation_t;
861
862 #define SHADERPERMUTATION_HASHSIZE 256
863
864
865 // non-degradable "lightweight" shader parameters to keep the permutations simpler
866 // these can NOT degrade! only use for simple stuff
867 enum
868 {
869         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
870         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
871         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
873         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
875         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
876 };
877 #define SHADERSTATICPARMS_COUNT 7
878
879 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
880 static int shaderstaticparms_count = 0;
881
882 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
883 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
884 qboolean R_CompileShader_CheckStaticParms(void)
885 {
886         static int r_compileshader_staticparms_save[1];
887         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
888         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
889
890         // detect all
891         if (r_glsl_saturation_redcompensate.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
893         if (r_glsl_vertextextureblend_usebothalphas.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
895         if (r_shadow_glossexact.integer)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
897         if (r_glsl_postprocess.integer)
898         {
899                 if (r_glsl_postprocess_uservec1_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
901                 if (r_glsl_postprocess_uservec2_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
903                 if (r_glsl_postprocess_uservec3_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
905                 if (r_glsl_postprocess_uservec4_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
907         }
908         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
909 }
910
911 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
912         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
913                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
914         else \
915                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
916 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
917 {
918         shaderstaticparms_count = 0;
919
920         // emit all
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
928 }
929
930 /// information about each possible shader permutation
931 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
932 /// currently selected permutation
933 r_glsl_permutation_t *r_glsl_permutation;
934 /// storage for permutations linked in the hash table
935 memexpandablearray_t r_glsl_permutationarray;
936
937 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
938 {
939         //unsigned int hashdepth = 0;
940         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
941         r_glsl_permutation_t *p;
942         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
943         {
944                 if (p->mode == mode && p->permutation == permutation)
945                 {
946                         //if (hashdepth > 10)
947                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948                         return p;
949                 }
950                 //hashdepth++;
951         }
952         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
953         p->mode = mode;
954         p->permutation = permutation;
955         p->hashnext = r_glsl_permutationhash[mode][hashindex];
956         r_glsl_permutationhash[mode][hashindex] = p;
957         //if (hashdepth > 10)
958         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
959         return p;
960 }
961
962 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
963 {
964         char *shaderstring;
965         if (!filename || !filename[0])
966                 return NULL;
967         if (!strcmp(filename, "glsl/default.glsl"))
968         {
969                 if (!glslshaderstring)
970                 {
971                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
972                         if (glslshaderstring)
973                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
974                         else
975                                 glslshaderstring = (char *)builtinshaderstring;
976                 }
977                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
978                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
979                 return shaderstring;
980         }
981         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
982         if (shaderstring)
983         {
984                 if (printfromdisknotice)
985                         Con_DPrintf("from disk %s... ", filename);
986                 return shaderstring;
987         }
988         return shaderstring;
989 }
990
991 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
992 {
993         int i;
994         int sampler;
995         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
996         char *vertexstring, *geometrystring, *fragmentstring;
997         char permutationname[256];
998         int vertstrings_count = 0;
999         int geomstrings_count = 0;
1000         int fragstrings_count = 0;
1001         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1004
1005         if (p->compiled)
1006                 return;
1007         p->compiled = true;
1008         p->program = 0;
1009
1010         permutationname[0] = 0;
1011         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1012         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1013         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1014
1015         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1016
1017         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1018         if(vid.support.gl20shaders130)
1019         {
1020                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1021                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1022                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1023                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1024                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1025                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1026         }
1027
1028         // the first pretext is which type of shader to compile as
1029         // (later these will all be bound together as a program object)
1030         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1031         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1032         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1033
1034         // the second pretext is the mode (for example a light source)
1035         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1036         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1037         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1038         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1039
1040         // now add all the permutation pretexts
1041         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1042         {
1043                 if (permutation & (1<<i))
1044                 {
1045                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1047                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1048                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1049                 }
1050                 else
1051                 {
1052                         // keep line numbers correct
1053                         vertstrings_list[vertstrings_count++] = "\n";
1054                         geomstrings_list[geomstrings_count++] = "\n";
1055                         fragstrings_list[fragstrings_count++] = "\n";
1056                 }
1057         }
1058
1059         // add static parms
1060         R_CompileShader_AddStaticParms(mode, permutation);
1061         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         vertstrings_count += shaderstaticparms_count;
1063         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064         geomstrings_count += shaderstaticparms_count;
1065         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1066         fragstrings_count += shaderstaticparms_count;
1067
1068         // now append the shader text itself
1069         vertstrings_list[vertstrings_count++] = vertexstring;
1070         geomstrings_list[geomstrings_count++] = geometrystring;
1071         fragstrings_list[fragstrings_count++] = fragmentstring;
1072
1073         // if any sources were NULL, clear the respective list
1074         if (!vertexstring)
1075                 vertstrings_count = 0;
1076         if (!geometrystring)
1077                 geomstrings_count = 0;
1078         if (!fragmentstring)
1079                 fragstrings_count = 0;
1080
1081         // compile the shader program
1082         if (vertstrings_count + geomstrings_count + fragstrings_count)
1083                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1084         if (p->program)
1085         {
1086                 CHECKGLERROR
1087                 qglUseProgram(p->program);CHECKGLERROR
1088                 // look up all the uniform variable names we care about, so we don't
1089                 // have to look them up every time we set them
1090
1091                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1092                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1093                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1094                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1095                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1096                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1097                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1098                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1099                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1100                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1101                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1102                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1103                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1104                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1105                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1106                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1107                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1108                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1109                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1110                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1111                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1112                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1113                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1114                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1115                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1116                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1117                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1118                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1119                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1120                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1121                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1122                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1123                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1124                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1125                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1126                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1127                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1128                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1129                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1130                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1131                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1132                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1133                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1134                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1135                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1136                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1137                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1138                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1139                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1140                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1141                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1142                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1143                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1144                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1145                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1146                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1147                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1148                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1149                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1150                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1151                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1152                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1153                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1154                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1155                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1156                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1157                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1158                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1159                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1160                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1161                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1162                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1163                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1164                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1165                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1166                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1167                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1168                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1169                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1170                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1171                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1172                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1173                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1174                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1175                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1176                 // initialize the samplers to refer to the texture units we use
1177                 p->tex_Texture_First = -1;
1178                 p->tex_Texture_Second = -1;
1179                 p->tex_Texture_GammaRamps = -1;
1180                 p->tex_Texture_Normal = -1;
1181                 p->tex_Texture_Color = -1;
1182                 p->tex_Texture_Gloss = -1;
1183                 p->tex_Texture_Glow = -1;
1184                 p->tex_Texture_SecondaryNormal = -1;
1185                 p->tex_Texture_SecondaryColor = -1;
1186                 p->tex_Texture_SecondaryGloss = -1;
1187                 p->tex_Texture_SecondaryGlow = -1;
1188                 p->tex_Texture_Pants = -1;
1189                 p->tex_Texture_Shirt = -1;
1190                 p->tex_Texture_FogHeightTexture = -1;
1191                 p->tex_Texture_FogMask = -1;
1192                 p->tex_Texture_Lightmap = -1;
1193                 p->tex_Texture_Deluxemap = -1;
1194                 p->tex_Texture_Attenuation = -1;
1195                 p->tex_Texture_Cube = -1;
1196                 p->tex_Texture_Refraction = -1;
1197                 p->tex_Texture_Reflection = -1;
1198                 p->tex_Texture_ShadowMap2D = -1;
1199                 p->tex_Texture_CubeProjection = -1;
1200                 p->tex_Texture_ScreenDepth = -1;
1201                 p->tex_Texture_ScreenNormalMap = -1;
1202                 p->tex_Texture_ScreenDiffuse = -1;
1203                 p->tex_Texture_ScreenSpecular = -1;
1204                 p->tex_Texture_ReflectMask = -1;
1205                 p->tex_Texture_ReflectCube = -1;
1206                 p->tex_Texture_BounceGrid = -1;
1207                 sampler = 0;
1208                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1209                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1210                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1211                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1212                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1213                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1214                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1217                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1218                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1219                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1220                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1221                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1222                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1223                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1224                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1225                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1226                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1227                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1228                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1229                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1230                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1233                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1234                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1235                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1236                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1237                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1238                 CHECKGLERROR
1239                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1240         }
1241         else
1242                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1243
1244         // free the strings
1245         if (vertexstring)
1246                 Mem_Free(vertexstring);
1247         if (geometrystring)
1248                 Mem_Free(geometrystring);
1249         if (fragmentstring)
1250                 Mem_Free(fragmentstring);
1251 }
1252
1253 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1254 {
1255         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1256         if (r_glsl_permutation != perm)
1257         {
1258                 r_glsl_permutation = perm;
1259                 if (!r_glsl_permutation->program)
1260                 {
1261                         if (!r_glsl_permutation->compiled)
1262                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                         if (!r_glsl_permutation->program)
1264                         {
1265                                 // remove features until we find a valid permutation
1266                                 int i;
1267                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1268                                 {
1269                                         // reduce i more quickly whenever it would not remove any bits
1270                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1271                                         if (!(permutation & j))
1272                                                 continue;
1273                                         permutation -= j;
1274                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1275                                         if (!r_glsl_permutation->compiled)
1276                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1277                                         if (r_glsl_permutation->program)
1278                                                 break;
1279                                 }
1280                                 if (i >= SHADERPERMUTATION_COUNT)
1281                                 {
1282                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1283                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1284                                         qglUseProgram(0);CHECKGLERROR
1285                                         return; // no bit left to clear, entire mode is broken
1286                                 }
1287                         }
1288                 }
1289                 CHECKGLERROR
1290                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1291         }
1292         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1293         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1294         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1295 }
1296
1297 #ifdef SUPPORTD3D
1298
1299 #ifdef SUPPORTD3D
1300 #include <d3d9.h>
1301 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1302 extern D3DCAPS9 vid_d3d9caps;
1303 #endif
1304
1305 struct r_hlsl_permutation_s;
1306 typedef struct r_hlsl_permutation_s
1307 {
1308         /// hash lookup data
1309         struct r_hlsl_permutation_s *hashnext;
1310         unsigned int mode;
1311         unsigned int permutation;
1312
1313         /// indicates if we have tried compiling this permutation already
1314         qboolean compiled;
1315         /// NULL if compilation failed
1316         IDirect3DVertexShader9 *vertexshader;
1317         IDirect3DPixelShader9 *pixelshader;
1318 }
1319 r_hlsl_permutation_t;
1320
1321 typedef enum D3DVSREGISTER_e
1322 {
1323         D3DVSREGISTER_TexMatrix = 0, // float4x4
1324         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1325         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1326         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1327         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1328         D3DVSREGISTER_ModelToLight = 20, // float4x4
1329         D3DVSREGISTER_EyePosition = 24,
1330         D3DVSREGISTER_FogPlane = 25,
1331         D3DVSREGISTER_LightDir = 26,
1332         D3DVSREGISTER_LightPosition = 27,
1333 }
1334 D3DVSREGISTER_t;
1335
1336 typedef enum D3DPSREGISTER_e
1337 {
1338         D3DPSREGISTER_Alpha = 0,
1339         D3DPSREGISTER_BloomBlur_Parameters = 1,
1340         D3DPSREGISTER_ClientTime = 2,
1341         D3DPSREGISTER_Color_Ambient = 3,
1342         D3DPSREGISTER_Color_Diffuse = 4,
1343         D3DPSREGISTER_Color_Specular = 5,
1344         D3DPSREGISTER_Color_Glow = 6,
1345         D3DPSREGISTER_Color_Pants = 7,
1346         D3DPSREGISTER_Color_Shirt = 8,
1347         D3DPSREGISTER_DeferredColor_Ambient = 9,
1348         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1349         D3DPSREGISTER_DeferredColor_Specular = 11,
1350         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1351         D3DPSREGISTER_DeferredMod_Specular = 13,
1352         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1353         D3DPSREGISTER_EyePosition = 15, // unused
1354         D3DPSREGISTER_FogColor = 16,
1355         D3DPSREGISTER_FogHeightFade = 17,
1356         D3DPSREGISTER_FogPlane = 18,
1357         D3DPSREGISTER_FogPlaneViewDist = 19,
1358         D3DPSREGISTER_FogRangeRecip = 20,
1359         D3DPSREGISTER_LightColor = 21,
1360         D3DPSREGISTER_LightDir = 22, // unused
1361         D3DPSREGISTER_LightPosition = 23,
1362         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1363         D3DPSREGISTER_PixelSize = 25,
1364         D3DPSREGISTER_ReflectColor = 26,
1365         D3DPSREGISTER_ReflectFactor = 27,
1366         D3DPSREGISTER_ReflectOffset = 28,
1367         D3DPSREGISTER_RefractColor = 29,
1368         D3DPSREGISTER_Saturation = 30,
1369         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1370         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1371         D3DPSREGISTER_ScreenToDepth = 33,
1372         D3DPSREGISTER_ShadowMap_Parameters = 34,
1373         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1374         D3DPSREGISTER_SpecularPower = 36,
1375         D3DPSREGISTER_UserVec1 = 37,
1376         D3DPSREGISTER_UserVec2 = 38,
1377         D3DPSREGISTER_UserVec3 = 39,
1378         D3DPSREGISTER_UserVec4 = 40,
1379         D3DPSREGISTER_ViewTintColor = 41,
1380         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1381         D3DPSREGISTER_BloomColorSubtract = 43,
1382         D3DPSREGISTER_ViewToLight = 44, // float4x4
1383         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1384         D3DPSREGISTER_NormalmapScrollBlend = 52,
1385         // next at 53
1386 }
1387 D3DPSREGISTER_t;
1388
1389 /// information about each possible shader permutation
1390 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1391 /// currently selected permutation
1392 r_hlsl_permutation_t *r_hlsl_permutation;
1393 /// storage for permutations linked in the hash table
1394 memexpandablearray_t r_hlsl_permutationarray;
1395
1396 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1397 {
1398         //unsigned int hashdepth = 0;
1399         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1400         r_hlsl_permutation_t *p;
1401         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1402         {
1403                 if (p->mode == mode && p->permutation == permutation)
1404                 {
1405                         //if (hashdepth > 10)
1406                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407                         return p;
1408                 }
1409                 //hashdepth++;
1410         }
1411         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1412         p->mode = mode;
1413         p->permutation = permutation;
1414         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1415         r_hlsl_permutationhash[mode][hashindex] = p;
1416         //if (hashdepth > 10)
1417         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1418         return p;
1419 }
1420
1421 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1422 {
1423         char *shaderstring;
1424         if (!filename || !filename[0])
1425                 return NULL;
1426         if (!strcmp(filename, "hlsl/default.hlsl"))
1427         {
1428                 if (!hlslshaderstring)
1429                 {
1430                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1431                         if (hlslshaderstring)
1432                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1433                         else
1434                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1435                 }
1436                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1437                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1438                 return shaderstring;
1439         }
1440         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441         if (shaderstring)
1442         {
1443                 if (printfromdisknotice)
1444                         Con_DPrintf("from disk %s... ", filename);
1445                 return shaderstring;
1446         }
1447         return shaderstring;
1448 }
1449
1450 #include <d3dx9.h>
1451 //#include <d3dx9shader.h>
1452 //#include <d3dx9mesh.h>
1453
1454 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1455 {
1456         DWORD *vsbin = NULL;
1457         DWORD *psbin = NULL;
1458         fs_offset_t vsbinsize;
1459         fs_offset_t psbinsize;
1460 //      IDirect3DVertexShader9 *vs = NULL;
1461 //      IDirect3DPixelShader9 *ps = NULL;
1462         ID3DXBuffer *vslog = NULL;
1463         ID3DXBuffer *vsbuffer = NULL;
1464         ID3DXConstantTable *vsconstanttable = NULL;
1465         ID3DXBuffer *pslog = NULL;
1466         ID3DXBuffer *psbuffer = NULL;
1467         ID3DXConstantTable *psconstanttable = NULL;
1468         int vsresult = 0;
1469         int psresult = 0;
1470         char temp[MAX_INPUTLINE];
1471         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1472         qboolean debugshader = gl_paranoid.integer != 0;
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1475         if (!debugshader)
1476         {
1477                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1478                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1479         }
1480         if ((!vsbin && vertstring) || (!psbin && fragstring))
1481         {
1482                 const char* dllnames_d3dx9 [] =
1483                 {
1484                         "d3dx9_43.dll",
1485                         "d3dx9_42.dll",
1486                         "d3dx9_41.dll",
1487                         "d3dx9_40.dll",
1488                         "d3dx9_39.dll",
1489                         "d3dx9_38.dll",
1490                         "d3dx9_37.dll",
1491                         "d3dx9_36.dll",
1492                         "d3dx9_35.dll",
1493                         "d3dx9_34.dll",
1494                         "d3dx9_33.dll",
1495                         "d3dx9_32.dll",
1496                         "d3dx9_31.dll",
1497                         "d3dx9_30.dll",
1498                         "d3dx9_29.dll",
1499                         "d3dx9_28.dll",
1500                         "d3dx9_27.dll",
1501                         "d3dx9_26.dll",
1502                         "d3dx9_25.dll",
1503                         "d3dx9_24.dll",
1504                         NULL
1505                 };
1506                 dllhandle_t d3dx9_dll = NULL;
1507                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1509                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1510                 dllfunction_t d3dx9_dllfuncs[] =
1511                 {
1512                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1513                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1514                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1515                         {NULL, NULL}
1516                 };
1517                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1518                 {
1519                         DWORD shaderflags = 0;
1520                         if (debugshader)
1521                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1522                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1523                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1524                         if (vertstring && vertstring[0])
1525                         {
1526                                 if (debugshader)
1527                                 {
1528 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1529 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1530                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1531                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532                                 }
1533                                 else
1534                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1535                                 if (vsbuffer)
1536                                 {
1537                                         vsbinsize = vsbuffer->GetBufferSize();
1538                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1539                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1540                                         vsbuffer->Release();
1541                                 }
1542                                 if (vslog)
1543                                 {
1544                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1545                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1546                                         vslog->Release();
1547                                 }
1548                         }
1549                         if (fragstring && fragstring[0])
1550                         {
1551                                 if (debugshader)
1552                                 {
1553 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1554 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1555                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1556                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557                                 }
1558                                 else
1559                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1560                                 if (psbuffer)
1561                                 {
1562                                         psbinsize = psbuffer->GetBufferSize();
1563                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1564                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1565                                         psbuffer->Release();
1566                                 }
1567                                 if (pslog)
1568                                 {
1569                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1570                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1571                                         pslog->Release();
1572                                 }
1573                         }
1574                         Sys_UnloadLibrary(&d3dx9_dll);
1575                 }
1576                 else
1577                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1578         }
1579         if (vsbin && psbin)
1580         {
1581                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1582                 if (FAILED(vsresult))
1583                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1584                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1585                 if (FAILED(psresult))
1586                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1587         }
1588         // free the shader data
1589         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1590         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1591 }
1592
1593 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1594 {
1595         int i;
1596         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1597         int vertstring_length = 0;
1598         int geomstring_length = 0;
1599         int fragstring_length = 0;
1600         char *t;
1601         char *vertexstring, *geometrystring, *fragmentstring;
1602         char *vertstring, *geomstring, *fragstring;
1603         char permutationname[256];
1604         char cachename[256];
1605         int vertstrings_count = 0;
1606         int geomstrings_count = 0;
1607         int fragstrings_count = 0;
1608         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1611
1612         if (p->compiled)
1613                 return;
1614         p->compiled = true;
1615         p->vertexshader = NULL;
1616         p->pixelshader = NULL;
1617
1618         permutationname[0] = 0;
1619         cachename[0] = 0;
1620         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1621         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1622         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1623
1624         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1625         strlcat(cachename, "hlsl/", sizeof(cachename));
1626
1627         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1628         vertstrings_count = 0;
1629         geomstrings_count = 0;
1630         fragstrings_count = 0;
1631         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1632         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1633         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1634
1635         // the first pretext is which type of shader to compile as
1636         // (later these will all be bound together as a program object)
1637         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1638         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1639         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1640
1641         // the second pretext is the mode (for example a light source)
1642         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1643         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1644         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1645         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1646         strlcat(cachename, modeinfo->name, sizeof(cachename));
1647
1648         // now add all the permutation pretexts
1649         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1650         {
1651                 if (permutation & (1<<i))
1652                 {
1653                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1656                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1657                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1658                 }
1659                 else
1660                 {
1661                         // keep line numbers correct
1662                         vertstrings_list[vertstrings_count++] = "\n";
1663                         geomstrings_list[geomstrings_count++] = "\n";
1664                         fragstrings_list[fragstrings_count++] = "\n";
1665                 }
1666         }
1667
1668         // add static parms
1669         R_CompileShader_AddStaticParms(mode, permutation);
1670         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         vertstrings_count += shaderstaticparms_count;
1672         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         geomstrings_count += shaderstaticparms_count;
1674         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1675         fragstrings_count += shaderstaticparms_count;
1676
1677         // replace spaces in the cachename with _ characters
1678         for (i = 0;cachename[i];i++)
1679                 if (cachename[i] == ' ')
1680                         cachename[i] = '_';
1681
1682         // now append the shader text itself
1683         vertstrings_list[vertstrings_count++] = vertexstring;
1684         geomstrings_list[geomstrings_count++] = geometrystring;
1685         fragstrings_list[fragstrings_count++] = fragmentstring;
1686
1687         // if any sources were NULL, clear the respective list
1688         if (!vertexstring)
1689                 vertstrings_count = 0;
1690         if (!geometrystring)
1691                 geomstrings_count = 0;
1692         if (!fragmentstring)
1693                 fragstrings_count = 0;
1694
1695         vertstring_length = 0;
1696         for (i = 0;i < vertstrings_count;i++)
1697                 vertstring_length += strlen(vertstrings_list[i]);
1698         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1699         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1700                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1701
1702         geomstring_length = 0;
1703         for (i = 0;i < geomstrings_count;i++)
1704                 geomstring_length += strlen(geomstrings_list[i]);
1705         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1706         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1707                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1708
1709         fragstring_length = 0;
1710         for (i = 0;i < fragstrings_count;i++)
1711                 fragstring_length += strlen(fragstrings_list[i]);
1712         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1713         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1714                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1715
1716         // try to load the cached shader, or generate one
1717         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1718
1719         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1720                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1721         else
1722                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1723
1724         // free the strings
1725         if (vertstring)
1726                 Mem_Free(vertstring);
1727         if (geomstring)
1728                 Mem_Free(geomstring);
1729         if (fragstring)
1730                 Mem_Free(fragstring);
1731         if (vertexstring)
1732                 Mem_Free(vertexstring);
1733         if (geometrystring)
1734                 Mem_Free(geometrystring);
1735         if (fragmentstring)
1736                 Mem_Free(fragmentstring);
1737 }
1738
1739 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1745
1746 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1752
1753 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1754 {
1755         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1756         if (r_hlsl_permutation != perm)
1757         {
1758                 r_hlsl_permutation = perm;
1759                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760                 {
1761                         if (!r_hlsl_permutation->compiled)
1762                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1764                         {
1765                                 // remove features until we find a valid permutation
1766                                 int i;
1767                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1768                                 {
1769                                         // reduce i more quickly whenever it would not remove any bits
1770                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1771                                         if (!(permutation & j))
1772                                                 continue;
1773                                         permutation -= j;
1774                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1775                                         if (!r_hlsl_permutation->compiled)
1776                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1777                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1778                                                 break;
1779                                 }
1780                                 if (i >= SHADERPERMUTATION_COUNT)
1781                                 {
1782                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1783                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784                                         return; // no bit left to clear, entire mode is broken
1785                                 }
1786                         }
1787                 }
1788                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1789                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1790         }
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1792         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1793         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1794 }
1795 #endif
1796
1797 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1798 {
1799         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1801         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1802         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1803 }
1804
1805 void R_GLSL_Restart_f(void)
1806 {
1807         unsigned int i, limit;
1808         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1809                 Mem_Free(glslshaderstring);
1810         glslshaderstring = NULL;
1811         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1812                 Mem_Free(hlslshaderstring);
1813         hlslshaderstring = NULL;
1814         switch(vid.renderpath)
1815         {
1816         case RENDERPATH_D3D9:
1817 #ifdef SUPPORTD3D
1818                 {
1819                         r_hlsl_permutation_t *p;
1820                         r_hlsl_permutation = NULL;
1821                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1822                         for (i = 0;i < limit;i++)
1823                         {
1824                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1825                                 {
1826                                         if (p->vertexshader)
1827                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1828                                         if (p->pixelshader)
1829                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1830                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1831                                 }
1832                         }
1833                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1834                 }
1835 #endif
1836                 break;
1837         case RENDERPATH_D3D10:
1838                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839                 break;
1840         case RENDERPATH_D3D11:
1841                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1842                 break;
1843         case RENDERPATH_GL20:
1844         case RENDERPATH_GLES2:
1845                 {
1846                         r_glsl_permutation_t *p;
1847                         r_glsl_permutation = NULL;
1848                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1849                         for (i = 0;i < limit;i++)
1850                         {
1851                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1852                                 {
1853                                         GL_Backend_FreeProgram(p->program);
1854                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1855                                 }
1856                         }
1857                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1858                 }
1859                 break;
1860         case RENDERPATH_GL11:
1861         case RENDERPATH_GL13:
1862         case RENDERPATH_GLES1:
1863                 break;
1864         case RENDERPATH_SOFT:
1865                 break;
1866         }
1867 }
1868
1869 void R_GLSL_DumpShader_f(void)
1870 {
1871         int i;
1872         qfile_t *file;
1873
1874         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1875         if (file)
1876         {
1877                 FS_Print(file, "/* The engine may define the following macros:\n");
1878                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879                 for (i = 0;i < SHADERMODE_COUNT;i++)
1880                         FS_Print(file, glslshadermodeinfo[i].pretext);
1881                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882                         FS_Print(file, shaderpermutationinfo[i].pretext);
1883                 FS_Print(file, "*/\n");
1884                 FS_Print(file, builtinshaderstring);
1885                 FS_Close(file);
1886                 Con_Printf("glsl/default.glsl written\n");
1887         }
1888         else
1889                 Con_Printf("failed to write to glsl/default.glsl\n");
1890
1891         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1892         if (file)
1893         {
1894                 FS_Print(file, "/* The engine may define the following macros:\n");
1895                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1896                 for (i = 0;i < SHADERMODE_COUNT;i++)
1897                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1898                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1899                         FS_Print(file, shaderpermutationinfo[i].pretext);
1900                 FS_Print(file, "*/\n");
1901                 FS_Print(file, builtinhlslshaderstring);
1902                 FS_Close(file);
1903                 Con_Printf("hlsl/default.hlsl written\n");
1904         }
1905         else
1906                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1907 }
1908
1909 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1910 {
1911         if (!second)
1912                 texturemode = GL_MODULATE;
1913         switch (vid.renderpath)
1914         {
1915         case RENDERPATH_D3D9:
1916 #ifdef SUPPORTD3D
1917                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1918                 R_Mesh_TexBind(GL20TU_FIRST , first );
1919                 R_Mesh_TexBind(GL20TU_SECOND, second);
1920 #endif
1921                 break;
1922         case RENDERPATH_D3D10:
1923                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1924                 break;
1925         case RENDERPATH_D3D11:
1926                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_GL20:
1929         case RENDERPATH_GLES2:
1930                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1931                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1932                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1933                 break;
1934         case RENDERPATH_GL13:
1935         case RENDERPATH_GLES1:
1936                 R_Mesh_TexBind(0, first );
1937                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1938                 R_Mesh_TexBind(1, second);
1939                 if (second)
1940                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1941                 break;
1942         case RENDERPATH_GL11:
1943                 R_Mesh_TexBind(0, first );
1944                 break;
1945         case RENDERPATH_SOFT:
1946                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 break;
1950         }
1951 }
1952
1953 void R_SetupShader_DepthOrShadow(void)
1954 {
1955         switch (vid.renderpath)
1956         {
1957         case RENDERPATH_D3D9:
1958 #ifdef SUPPORTD3D
1959                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1960 #endif
1961                 break;
1962         case RENDERPATH_D3D10:
1963                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_D3D11:
1966                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1967                 break;
1968         case RENDERPATH_GL20:
1969         case RENDERPATH_GLES2:
1970                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1971                 break;
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 R_Mesh_TexBind(0, 0);
1975                 R_Mesh_TexBind(1, 0);
1976                 break;
1977         case RENDERPATH_GL11:
1978                 R_Mesh_TexBind(0, 0);
1979                 break;
1980         case RENDERPATH_SOFT:
1981                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_ShowDepth(void)
1987 {
1988         switch (vid.renderpath)
1989         {
1990         case RENDERPATH_D3D9:
1991 #ifdef SUPPORTHLSL
1992                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1993 #endif
1994                 break;
1995         case RENDERPATH_D3D10:
1996                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1997                 break;
1998         case RENDERPATH_D3D11:
1999                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2000                 break;
2001         case RENDERPATH_GL20:
2002         case RENDERPATH_GLES2:
2003                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2004                 break;
2005         case RENDERPATH_GL13:
2006         case RENDERPATH_GLES1:
2007                 break;
2008         case RENDERPATH_GL11:
2009                 break;
2010         case RENDERPATH_SOFT:
2011                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2012                 break;
2013         }
2014 }
2015
2016 extern qboolean r_shadow_usingdeferredprepass;
2017 extern cvar_t r_shadow_deferred_8bitrange;
2018 extern rtexture_t *r_shadow_attenuationgradienttexture;
2019 extern rtexture_t *r_shadow_attenuation2dtexture;
2020 extern rtexture_t *r_shadow_attenuation3dtexture;
2021 extern qboolean r_shadow_usingshadowmap2d;
2022 extern qboolean r_shadow_usingshadowmaportho;
2023 extern float r_shadow_shadowmap_texturescale[2];
2024 extern float r_shadow_shadowmap_parameters[4];
2025 extern qboolean r_shadow_shadowmapvsdct;
2026 extern qboolean r_shadow_shadowmapsampler;
2027 extern int r_shadow_shadowmappcf;
2028 extern rtexture_t *r_shadow_shadowmap2dtexture;
2029 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2030 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2031 extern matrix4x4_t r_shadow_shadowmapmatrix;
2032 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2033 extern int r_shadow_prepass_width;
2034 extern int r_shadow_prepass_height;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2036 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2037 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2038 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2039 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2040
2041 #define BLENDFUNC_ALLOWS_COLORMOD      1
2042 #define BLENDFUNC_ALLOWS_FOG           2
2043 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2044 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2045 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2046 static int R_BlendFuncFlags(int src, int dst)
2047 {
2048         int r = 0;
2049
2050         // a blendfunc allows colormod if:
2051         // a) it can never keep the destination pixel invariant, or
2052         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2053         // this is to prevent unintended side effects from colormod
2054
2055         // a blendfunc allows fog if:
2056         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2057         // this is to prevent unintended side effects from fog
2058
2059         // these checks are the output of fogeval.pl
2060
2061         r |= BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2071         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2072         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2076         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2077         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2080         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083
2084         return r;
2085 }
2086
2087 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)
2088 {
2089         // select a permutation of the lighting shader appropriate to this
2090         // combination of texture, entity, light source, and fogging, only use the
2091         // minimum features necessary to avoid wasting rendering time in the
2092         // fragment shader on features that are not being used
2093         unsigned int permutation = 0;
2094         unsigned int mode = 0;
2095         int blendfuncflags;
2096         static float dummy_colormod[3] = {1, 1, 1};
2097         float *colormod = rsurface.colormod;
2098         float m16f[16];
2099         matrix4x4_t tempmatrix;
2100         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2101         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2102                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2103         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2104                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2105         if (rsurfacepass == RSURFPASS_BACKGROUND)
2106         {
2107                 // distorted background
2108                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2109                 {
2110                         mode = SHADERMODE_WATER;
2111                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2112                         {
2113                                 // this is the right thing to do for wateralpha
2114                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2115                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2116                         }
2117                         else
2118                         {
2119                                 // this is the right thing to do for entity alpha
2120                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122                         }
2123                 }
2124                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2125                 {
2126                         mode = SHADERMODE_REFRACTION;
2127                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2128                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2129                 }
2130                 else
2131                 {
2132                         mode = SHADERMODE_GENERIC;
2133                         permutation |= SHADERPERMUTATION_DIFFUSE;
2134                         GL_BlendFunc(GL_ONE, GL_ZERO);
2135                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136                 }
2137         }
2138         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2139         {
2140                 if (r_glsl_offsetmapping.integer)
2141                 {
2142                         switch(rsurface.texture->offsetmapping)
2143                         {
2144                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2145                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2146                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2147                         case OFFSETMAPPING_OFF: break;
2148                         }
2149                 }
2150                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2151                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152                 // normalmap (deferred prepass), may use alpha test on diffuse
2153                 mode = SHADERMODE_DEFERREDGEOMETRY;
2154                 GL_BlendFunc(GL_ONE, GL_ZERO);
2155                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156         }
2157         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2158         {
2159                 if (r_glsl_offsetmapping.integer)
2160                 {
2161                         switch(rsurface.texture->offsetmapping)
2162                         {
2163                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_OFF: break;
2167                         }
2168                 }
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 // light source
2172                 mode = SHADERMODE_LIGHTSOURCE;
2173                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2174                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2175                 if (diffusescale > 0)
2176                         permutation |= SHADERPERMUTATION_DIFFUSE;
2177                 if (specularscale > 0)
2178                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2179                 if (r_refdef.fogenabled)
2180                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2181                 if (rsurface.texture->colormapping)
2182                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2183                 if (r_shadow_usingshadowmap2d)
2184                 {
2185                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2186                         if(r_shadow_shadowmapvsdct)
2187                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2188
2189                         if (r_shadow_shadowmapsampler)
2190                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2191                         if (r_shadow_shadowmappcf > 1)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2193                         else if (r_shadow_shadowmappcf)
2194                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2195                 }
2196                 if (rsurface.texture->reflectmasktexture)
2197                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2198                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2199                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2200         }
2201         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2202         {
2203                 if (r_glsl_offsetmapping.integer)
2204                 {
2205                         switch(rsurface.texture->offsetmapping)
2206                         {
2207                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210                         case OFFSETMAPPING_OFF: break;
2211                         }
2212                 }
2213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215                 // unshaded geometry (fullbright or ambient model lighting)
2216                 mode = SHADERMODE_FLATCOLOR;
2217                 ambientscale = diffusescale = specularscale = 0;
2218                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2219                         permutation |= SHADERPERMUTATION_GLOW;
2220                 if (r_refdef.fogenabled)
2221                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222                 if (rsurface.texture->colormapping)
2223                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2224                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2225                 {
2226                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2227                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2228
2229                         if (r_shadow_shadowmapsampler)
2230                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2231                         if (r_shadow_shadowmappcf > 1)
2232                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2233                         else if (r_shadow_shadowmappcf)
2234                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2237                         permutation |= SHADERPERMUTATION_REFLECTION;
2238                 if (rsurface.texture->reflectmasktexture)
2239                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2240                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242         }
2243         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2244         {
2245                 if (r_glsl_offsetmapping.integer)
2246                 {
2247                         switch(rsurface.texture->offsetmapping)
2248                         {
2249                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2250                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252                         case OFFSETMAPPING_OFF: break;
2253                         }
2254                 }
2255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257                 // directional model lighting
2258                 mode = SHADERMODE_LIGHTDIRECTION;
2259                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2260                         permutation |= SHADERPERMUTATION_GLOW;
2261                 permutation |= SHADERPERMUTATION_DIFFUSE;
2262                 if (specularscale > 0)
2263                         permutation |= SHADERPERMUTATION_SPECULAR;
2264                 if (r_refdef.fogenabled)
2265                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2266                 if (rsurface.texture->colormapping)
2267                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2268                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2269                 {
2270                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2271                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2272
2273                         if (r_shadow_shadowmapsampler)
2274                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2275                         if (r_shadow_shadowmappcf > 1)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2277                         else if (r_shadow_shadowmappcf)
2278                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2279                 }
2280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281                         permutation |= SHADERPERMUTATION_REFLECTION;
2282                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2283                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2284                 if (rsurface.texture->reflectmasktexture)
2285                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2286                 if (r_shadow_bouncegridtexture)
2287                 {
2288                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2289                         if (r_shadow_bouncegriddirectional)
2290                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2291                 }
2292                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294         }
2295         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2296         {
2297                 if (r_glsl_offsetmapping.integer)
2298                 {
2299                         switch(rsurface.texture->offsetmapping)
2300                         {
2301                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_OFF: break;
2305                         }
2306                 }
2307                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309                 // ambient model lighting
2310                 mode = SHADERMODE_LIGHTDIRECTION;
2311                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2312                         permutation |= SHADERPERMUTATION_GLOW;
2313                 if (r_refdef.fogenabled)
2314                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315                 if (rsurface.texture->colormapping)
2316                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2317                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2318                 {
2319                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2321
2322                         if (r_shadow_shadowmapsampler)
2323                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324                         if (r_shadow_shadowmappcf > 1)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326                         else if (r_shadow_shadowmappcf)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330                         permutation |= SHADERPERMUTATION_REFLECTION;
2331                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333                 if (rsurface.texture->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 if (r_shadow_bouncegridtexture)
2336                 {
2337                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338                         if (r_shadow_bouncegriddirectional)
2339                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2340                 }
2341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343         }
2344         else
2345         {
2346                 if (r_glsl_offsetmapping.integer)
2347                 {
2348                         switch(rsurface.texture->offsetmapping)
2349                         {
2350                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2351                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353                         case OFFSETMAPPING_OFF: break;
2354                         }
2355                 }
2356                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2357                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2358                 // lightmapped wall
2359                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360                         permutation |= SHADERPERMUTATION_GLOW;
2361                 if (r_refdef.fogenabled)
2362                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363                 if (rsurface.texture->colormapping)
2364                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2365                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2366                 {
2367                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2369
2370                         if (r_shadow_shadowmapsampler)
2371                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372                         if (r_shadow_shadowmappcf > 1)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374                         else if (r_shadow_shadowmappcf)
2375                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378                         permutation |= SHADERPERMUTATION_REFLECTION;
2379                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381                 if (rsurface.texture->reflectmasktexture)
2382                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383                 if (FAKELIGHT_ENABLED)
2384                 {
2385                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2386                         mode = SHADERMODE_FAKELIGHT;
2387                         permutation |= SHADERPERMUTATION_DIFFUSE;
2388                         if (specularscale > 0)
2389                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2390                 }
2391                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2392                 {
2393                         // deluxemapping (light direction texture)
2394                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2395                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2396                         else
2397                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398                         permutation |= SHADERPERMUTATION_DIFFUSE;
2399                         if (specularscale > 0)
2400                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401                 }
2402                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2403                 {
2404                         // fake deluxemapping (uniform light direction in tangentspace)
2405                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2406                         permutation |= SHADERPERMUTATION_DIFFUSE;
2407                         if (specularscale > 0)
2408                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2409                 }
2410                 else if (rsurface.uselightmaptexture)
2411                 {
2412                         // ordinary lightmapping (q1bsp, q3bsp)
2413                         mode = SHADERMODE_LIGHTMAP;
2414                 }
2415                 else
2416                 {
2417                         // ordinary vertex coloring (q3bsp)
2418                         mode = SHADERMODE_VERTEXCOLOR;
2419                 }
2420                 if (r_shadow_bouncegridtexture)
2421                 {
2422                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2423                         if (r_shadow_bouncegriddirectional)
2424                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2425                 }
2426                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2428         }
2429         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2430                 colormod = dummy_colormod;
2431         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2432                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2433         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2434                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2435         switch(vid.renderpath)
2436         {
2437         case RENDERPATH_D3D9:
2438 #ifdef SUPPORTD3D
2439                 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);
2440                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2441                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2442                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2443                 if (mode == SHADERMODE_LIGHTSOURCE)
2444                 {
2445                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2446                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2447                 }
2448                 else
2449                 {
2450                         if (mode == SHADERMODE_LIGHTDIRECTION)
2451                         {
2452                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2453                         }
2454                 }
2455                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2456                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2457                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2458                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2459                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2460
2461                 if (mode == SHADERMODE_LIGHTSOURCE)
2462                 {
2463                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2464                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2465                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2466                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2467                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2468
2469                         // additive passes are only darkened by fog, not tinted
2470                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2472                 }
2473                 else
2474                 {
2475                         if (mode == SHADERMODE_FLATCOLOR)
2476                         {
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2478                         }
2479                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2480                         {
2481                                 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]);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2483                                 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);
2484                                 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);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2488                         }
2489                         else
2490                         {
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2493                                 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);
2494                                 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);
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496                         }
2497                         // additive passes are only darkened by fog, not tinted
2498                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2500                         else
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2502                         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);
2503                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2504                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2505                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2506                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2507                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2508                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2509                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2510                         if (mode == SHADERMODE_WATER)
2511                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2512                 }
2513                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2514                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2515                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2516                 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));
2517                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2518                 if (rsurface.texture->pantstexture)
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2520                 else
2521                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2522                 if (rsurface.texture->shirttexture)
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2524                 else
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2526                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2528                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2529                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2530                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2531                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2532                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2533                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2534                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2535                         );
2536                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2537                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2538
2539                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2540                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2541                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2542                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2545                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2546                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2547                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2548                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2549                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2550                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2551                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2552                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2553                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2554                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2555                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2556                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2557                 {
2558                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2559                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2560                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2561                 }
2562                 else
2563                 {
2564                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2565                 }
2566 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2567 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2568                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2569                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2570                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2571                 {
2572                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2573                         if (rsurface.rtlight)
2574                         {
2575                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2576                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2577                         }
2578                 }
2579 #endif
2580                 break;
2581         case RENDERPATH_D3D10:
2582                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2583                 break;
2584         case RENDERPATH_D3D11:
2585                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2586                 break;
2587         case RENDERPATH_GL20:
2588         case RENDERPATH_GLES2:
2589                 if (!vid.useinterleavedarrays)
2590                 {
2591                         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);
2592                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2593                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2597                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2598                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2599                 }
2600                 else
2601                 {
2602                         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);
2603                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2604                 }
2605                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2606                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2607                 if (mode == SHADERMODE_LIGHTSOURCE)
2608                 {
2609                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2610                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2612                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2613                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2614                         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);
2615         
2616                         // additive passes are only darkened by fog, not tinted
2617                         if (r_glsl_permutation->loc_FogColor >= 0)
2618                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2619                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2620                 }
2621                 else
2622                 {
2623                         if (mode == SHADERMODE_FLATCOLOR)
2624                         {
2625                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2626                         }
2627                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2628                         {
2629                                 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]);
2630                                 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]);
2631                                 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);
2632                                 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);
2633                                 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);
2634                                 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]);
2635                                 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]);
2636                         }
2637                         else
2638                         {
2639                                 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]);
2640                                 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]);
2641                                 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);
2642                                 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);
2643                                 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);
2644                         }
2645                         // additive passes are only darkened by fog, not tinted
2646                         if (r_glsl_permutation->loc_FogColor >= 0)
2647                         {
2648                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2649                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2650                                 else
2651                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2652                         }
2653                         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);
2654                         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]);
2655                         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]);
2656                         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]);
2657                         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]);
2658                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2659                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2660                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2661                         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]);
2662                 }
2663                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2665                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2666                 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]);
2667                 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]);
2668
2669                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2670                 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));
2671                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2672                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2673                 {
2674                         if (rsurface.texture->pantstexture)
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2676                         else
2677                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2678                 }
2679                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2680                 {
2681                         if (rsurface.texture->shirttexture)
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2683                         else
2684                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2685                 }
2686                 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]);
2687                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2689                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2690                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2691                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2695                         );
2696                 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]);
2697                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698                 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);}
2699                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2700
2701                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2702                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2703                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2704                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2705                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2706                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2710                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2711                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2712                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2714                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2715                 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);
2716                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2717                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2718                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         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);
2724                         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);
2725                         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);
2726                 }
2727                 else
2728                 {
2729                         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);
2730                 }
2731                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2732                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2741                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745                 CHECKGLERROR
2746                 break;
2747         case RENDERPATH_GL11:
2748         case RENDERPATH_GL13:
2749         case RENDERPATH_GLES1:
2750                 break;
2751         case RENDERPATH_SOFT:
2752                 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);
2753                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2754                 R_SetupShader_SetPermutationSoft(mode, permutation);
2755                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2756                 if (mode == SHADERMODE_LIGHTSOURCE)
2757                 {
2758                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2764         
2765                         // additive passes are only darkened by fog, not tinted
2766                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2767                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2768                 }
2769                 else
2770                 {
2771                         if (mode == SHADERMODE_FLATCOLOR)
2772                         {
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2774                         }
2775                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2776                         {
2777                                 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]);
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2779                                 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);
2780                                 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);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2782                                 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]);
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2784                         }
2785                         else
2786                         {
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2789                                 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);
2790                                 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);
2791                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2792                         }
2793                         // additive passes are only darkened by fog, not tinted
2794                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2795                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2796                         else
2797                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2798                         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);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2800                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2801                         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]);
2802                         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]);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2804                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2805                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2806                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2807                 }
2808                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2809                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2810                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2811                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2812                 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]);
2813
2814                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2815                 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));
2816                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2817                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2818                 {
2819                         if (rsurface.texture->pantstexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2823                 }
2824                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2825                 {
2826                         if (rsurface.texture->shirttexture)
2827                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2828                         else
2829                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2830                 }
2831                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2833                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2834                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2835                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2836                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2837                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2838                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2839                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2840                         );
2841                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2842                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2843
2844                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2845                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2846                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2847                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2848                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2849                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2850                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2851                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2852                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2853                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2854                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2855                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2856                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2857                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2858                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2859                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2860                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2861                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2862                 {
2863                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2864                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2865                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2866                 }
2867                 else
2868                 {
2869                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2870                 }
2871 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2872 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2873                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2874                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2875                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2876                 {
2877                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2878                         if (rsurface.rtlight)
2879                         {
2880                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2881                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2882                         }
2883                 }
2884                 break;
2885         }
2886 }
2887
2888 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2889 {
2890         // select a permutation of the lighting shader appropriate to this
2891         // combination of texture, entity, light source, and fogging, only use the
2892         // minimum features necessary to avoid wasting rendering time in the
2893         // fragment shader on features that are not being used
2894         unsigned int permutation = 0;
2895         unsigned int mode = 0;
2896         const float *lightcolorbase = rtlight->currentcolor;
2897         float ambientscale = rtlight->ambientscale;
2898         float diffusescale = rtlight->diffusescale;
2899         float specularscale = rtlight->specularscale;
2900         // this is the location of the light in view space
2901         vec3_t viewlightorigin;
2902         // this transforms from view space (camera) to light space (cubemap)
2903         matrix4x4_t viewtolight;
2904         matrix4x4_t lighttoview;
2905         float viewtolight16f[16];
2906         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2907         // light source
2908         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2909         if (rtlight->currentcubemap != r_texture_whitecube)
2910                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2911         if (diffusescale > 0)
2912                 permutation |= SHADERPERMUTATION_DIFFUSE;
2913         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2914                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2915         if (r_shadow_usingshadowmap2d)
2916         {
2917                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2918                 if (r_shadow_shadowmapvsdct)
2919                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2920
2921                 if (r_shadow_shadowmapsampler)
2922                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2923                 if (r_shadow_shadowmappcf > 1)
2924                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2925                 else if (r_shadow_shadowmappcf)
2926                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2927         }
2928         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2929         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2930         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2931         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2932         switch(vid.renderpath)
2933         {
2934         case RENDERPATH_D3D9:
2935 #ifdef SUPPORTD3D
2936                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2937                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2939                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2940                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2941                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2942                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2943                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2944                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2945                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2946                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2947
2948                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2949                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2950                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2951                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2952                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2953                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2954 #endif
2955                 break;
2956         case RENDERPATH_D3D10:
2957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2958                 break;
2959         case RENDERPATH_D3D11:
2960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2961                 break;
2962         case RENDERPATH_GL20:
2963         case RENDERPATH_GLES2:
2964                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2967                 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);
2968                 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);
2969                 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);
2970                 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]);
2971                 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]);
2972                 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));
2973                 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]);
2974                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2975
2976                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2977                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2978                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2979                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2980                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2981                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2982                 break;
2983         case RENDERPATH_GL11:
2984         case RENDERPATH_GL13:
2985         case RENDERPATH_GLES1:
2986                 break;
2987         case RENDERPATH_SOFT:
2988                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2989                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2990                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2991                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2992                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2993                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2994                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2995                 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]);
2996                 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));
2997                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2998                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2999
3000                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3001                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3002                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3003                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3004                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3005                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3006                 break;
3007         }
3008 }
3009
3010 #define SKINFRAME_HASH 1024
3011
3012 typedef struct
3013 {
3014         int loadsequence; // incremented each level change
3015         memexpandablearray_t array;
3016         skinframe_t *hash[SKINFRAME_HASH];
3017 }
3018 r_skinframe_t;
3019 r_skinframe_t r_skinframe;
3020
3021 void R_SkinFrame_PrepareForPurge(void)
3022 {
3023         r_skinframe.loadsequence++;
3024         // wrap it without hitting zero
3025         if (r_skinframe.loadsequence >= 200)
3026                 r_skinframe.loadsequence = 1;
3027 }
3028
3029 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3030 {
3031         if (!skinframe)
3032                 return;
3033         // mark the skinframe as used for the purging code
3034         skinframe->loadsequence = r_skinframe.loadsequence;
3035 }
3036
3037 void R_SkinFrame_Purge(void)
3038 {
3039         int i;
3040         skinframe_t *s;
3041         for (i = 0;i < SKINFRAME_HASH;i++)
3042         {
3043                 for (s = r_skinframe.hash[i];s;s = s->next)
3044                 {
3045                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3046                         {
3047                                 if (s->merged == s->base)
3048                                         s->merged = NULL;
3049                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3050                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3051                                 R_PurgeTexture(s->merged);s->merged = NULL;
3052                                 R_PurgeTexture(s->base  );s->base   = NULL;
3053                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3054                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3055                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3056                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3057                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3058                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3059                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3060                                 s->loadsequence = 0;
3061                         }
3062                 }
3063         }
3064 }
3065
3066 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3067         skinframe_t *item;
3068         char basename[MAX_QPATH];
3069
3070         Image_StripImageExtension(name, basename, sizeof(basename));
3071
3072         if( last == NULL ) {
3073                 int hashindex;
3074                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075                 item = r_skinframe.hash[hashindex];
3076         } else {
3077                 item = last->next;
3078         }
3079
3080         // linearly search through the hash bucket
3081         for( ; item ; item = item->next ) {
3082                 if( !strcmp( item->basename, basename ) ) {
3083                         return item;
3084                 }
3085         }
3086         return NULL;
3087 }
3088
3089 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3090 {
3091         skinframe_t *item;
3092         int hashindex;
3093         char basename[MAX_QPATH];
3094
3095         Image_StripImageExtension(name, basename, sizeof(basename));
3096
3097         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3098         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3099                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3100                         break;
3101
3102         if (!item) {
3103                 rtexture_t *dyntexture;
3104                 // check whether its a dynamic texture
3105                 dyntexture = CL_GetDynTexture( basename );
3106                 if (!add && !dyntexture)
3107                         return NULL;
3108                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3109                 memset(item, 0, sizeof(*item));
3110                 strlcpy(item->basename, basename, sizeof(item->basename));
3111                 item->base = dyntexture; // either NULL or dyntexture handle
3112                 item->textureflags = textureflags;
3113                 item->comparewidth = comparewidth;
3114                 item->compareheight = compareheight;
3115                 item->comparecrc = comparecrc;
3116                 item->next = r_skinframe.hash[hashindex];
3117                 r_skinframe.hash[hashindex] = item;
3118         }
3119         else if( item->base == NULL )
3120         {
3121                 rtexture_t *dyntexture;
3122                 // check whether its a dynamic texture
3123                 // 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]
3124                 dyntexture = CL_GetDynTexture( basename );
3125                 item->base = dyntexture; // either NULL or dyntexture handle
3126         }
3127
3128         R_SkinFrame_MarkUsed(item);
3129         return item;
3130 }
3131
3132 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3133         { \
3134                 unsigned long long avgcolor[5], wsum; \
3135                 int pix, comp, w; \
3136                 avgcolor[0] = 0; \
3137                 avgcolor[1] = 0; \
3138                 avgcolor[2] = 0; \
3139                 avgcolor[3] = 0; \
3140                 avgcolor[4] = 0; \
3141                 wsum = 0; \
3142                 for(pix = 0; pix < cnt; ++pix) \
3143                 { \
3144                         w = 0; \
3145                         for(comp = 0; comp < 3; ++comp) \
3146                                 w += getpixel; \
3147                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3148                         { \
3149                                 ++wsum; \
3150                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3151                                 w = getpixel; \
3152                                 for(comp = 0; comp < 3; ++comp) \
3153                                         avgcolor[comp] += getpixel * w; \
3154                                 avgcolor[3] += w; \
3155                         } \
3156                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3157                         avgcolor[4] += getpixel; \
3158                 } \
3159                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3160                         avgcolor[3] = 1; \
3161                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3162                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3163                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3164                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3165         }
3166
3167 extern cvar_t gl_picmip;
3168 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3169 {
3170         int j;
3171         unsigned char *pixels;
3172         unsigned char *bumppixels;
3173         unsigned char *basepixels = NULL;
3174         int basepixels_width = 0;
3175         int basepixels_height = 0;
3176         skinframe_t *skinframe;
3177         rtexture_t *ddsbase = NULL;
3178         qboolean ddshasalpha = false;
3179         float ddsavgcolor[4];
3180         char basename[MAX_QPATH];
3181         int miplevel = R_PicmipForFlags(textureflags);
3182         int savemiplevel = miplevel;
3183         int mymiplevel;
3184
3185         if (cls.state == ca_dedicated)
3186                 return NULL;
3187
3188         // return an existing skinframe if already loaded
3189         // if loading of the first image fails, don't make a new skinframe as it
3190         // would cause all future lookups of this to be missing
3191         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3192         if (skinframe && skinframe->base)
3193                 return skinframe;
3194
3195         Image_StripImageExtension(name, basename, sizeof(basename));
3196
3197         // check for DDS texture file first
3198         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3199         {
3200                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3201                 if (basepixels == NULL)
3202                         return NULL;
3203         }
3204
3205         // FIXME handle miplevel
3206
3207         if (developer_loading.integer)
3208                 Con_Printf("loading skin \"%s\"\n", name);
3209
3210         // we've got some pixels to store, so really allocate this new texture now
3211         if (!skinframe)
3212                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3213         skinframe->stain = NULL;
3214         skinframe->merged = NULL;
3215         skinframe->base = NULL;
3216         skinframe->pants = NULL;
3217         skinframe->shirt = NULL;
3218         skinframe->nmap = NULL;
3219         skinframe->gloss = NULL;
3220         skinframe->glow = NULL;
3221         skinframe->fog = NULL;
3222         skinframe->reflect = NULL;
3223         skinframe->hasalpha = false;
3224
3225         if (ddsbase)
3226         {
3227                 skinframe->base = ddsbase;
3228                 skinframe->hasalpha = ddshasalpha;
3229                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3230                 if (r_loadfog && skinframe->hasalpha)
3231                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3232                 //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]);
3233         }
3234         else
3235         {
3236                 basepixels_width = image_width;
3237                 basepixels_height = image_height;
3238                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3239                 if (textureflags & TEXF_ALPHA)
3240                 {
3241                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3242                         {
3243                                 if (basepixels[j] < 255)
3244                                 {
3245                                         skinframe->hasalpha = true;
3246                                         break;
3247                                 }
3248                         }
3249                         if (r_loadfog && skinframe->hasalpha)
3250                         {
3251                                 // has transparent pixels
3252                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3253                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3254                                 {
3255                                         pixels[j+0] = 255;
3256                                         pixels[j+1] = 255;
3257                                         pixels[j+2] = 255;
3258                                         pixels[j+3] = basepixels[j+3];
3259                                 }
3260                                 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);
3261                                 Mem_Free(pixels);
3262                         }
3263                 }
3264                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3265                 //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]);
3266                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3267                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3268                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3269                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3270         }
3271
3272         if (r_loaddds)
3273         {
3274                 mymiplevel = savemiplevel;
3275                 if (r_loadnormalmap)
3276                         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);
3277                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278                 if (r_loadgloss)
3279                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3282                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3283         }
3284
3285         // _norm is the name used by tenebrae and has been adopted as standard
3286         if (r_loadnormalmap && skinframe->nmap == NULL)
3287         {
3288                 mymiplevel = savemiplevel;
3289                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290                 {
3291                         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);
3292                         Mem_Free(pixels);
3293                         pixels = NULL;
3294                 }
3295                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3296                 {
3297                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3298                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3299                         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);
3300                         Mem_Free(pixels);
3301                         Mem_Free(bumppixels);
3302                 }
3303                 else if (r_shadow_bumpscale_basetexture.value > 0)
3304                 {
3305                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3306                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3307                         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);
3308                         Mem_Free(pixels);
3309                 }
3310                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3311                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3312         }
3313
3314         // _luma is supported only for tenebrae compatibility
3315         // _glow is the preferred name
3316         mymiplevel = savemiplevel;
3317         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))))
3318         {
3319                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3320                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3321                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3322                 Mem_Free(pixels);pixels = NULL;
3323         }
3324
3325         mymiplevel = savemiplevel;
3326         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3327         {
3328                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3329                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3330                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3331                 Mem_Free(pixels);
3332                 pixels = NULL;
3333         }
3334
3335         mymiplevel = savemiplevel;
3336         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3337         {
3338                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3339                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3340                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3341                 Mem_Free(pixels);
3342                 pixels = NULL;
3343         }
3344
3345         mymiplevel = savemiplevel;
3346         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3347         {
3348                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3349                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3350                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3351                 Mem_Free(pixels);
3352                 pixels = NULL;
3353         }
3354
3355         mymiplevel = savemiplevel;
3356         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3357         {
3358                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3359                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3360                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3361                 Mem_Free(pixels);
3362                 pixels = NULL;
3363         }
3364
3365         if (basepixels)
3366                 Mem_Free(basepixels);
3367
3368         return skinframe;
3369 }
3370
3371 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3372 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3373 {
3374         int i;
3375         unsigned char *temp1, *temp2;
3376         skinframe_t *skinframe;
3377
3378         if (cls.state == ca_dedicated)
3379                 return NULL;
3380
3381         // if already loaded just return it, otherwise make a new skinframe
3382         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3383         if (skinframe && skinframe->base)
3384                 return skinframe;
3385
3386         skinframe->stain = NULL;
3387         skinframe->merged = NULL;
3388         skinframe->base = NULL;
3389         skinframe->pants = NULL;
3390         skinframe->shirt = NULL;
3391         skinframe->nmap = NULL;
3392         skinframe->gloss = NULL;
3393         skinframe->glow = NULL;
3394         skinframe->fog = NULL;
3395         skinframe->reflect = NULL;
3396         skinframe->hasalpha = false;
3397
3398         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3399         if (!skindata)
3400                 return NULL;
3401
3402         if (developer_loading.integer)
3403                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3404
3405         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3406         {
3407                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3408                 temp2 = temp1 + width * height * 4;
3409                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3410                 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);
3411                 Mem_Free(temp1);
3412         }
3413         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3414         if (textureflags & TEXF_ALPHA)
3415         {
3416                 for (i = 3;i < width * height * 4;i += 4)
3417                 {
3418                         if (skindata[i] < 255)
3419                         {
3420                                 skinframe->hasalpha = true;
3421                                 break;
3422                         }
3423                 }
3424                 if (r_loadfog && skinframe->hasalpha)
3425                 {
3426                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3427                         memcpy(fogpixels, skindata, width * height * 4);
3428                         for (i = 0;i < width * height * 4;i += 4)
3429                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3430                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3431                         Mem_Free(fogpixels);
3432                 }
3433         }
3434
3435         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3436         //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]);
3437
3438         return skinframe;
3439 }
3440
3441 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3442 {
3443         int i;
3444         int featuresmask;
3445         skinframe_t *skinframe;
3446
3447         if (cls.state == ca_dedicated)
3448                 return NULL;
3449
3450         // if already loaded just return it, otherwise make a new skinframe
3451         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3452         if (skinframe && skinframe->base)
3453                 return skinframe;
3454
3455         skinframe->stain = NULL;
3456         skinframe->merged = NULL;
3457         skinframe->base = NULL;
3458         skinframe->pants = NULL;
3459         skinframe->shirt = NULL;
3460         skinframe->nmap = NULL;
3461         skinframe->gloss = NULL;
3462         skinframe->glow = NULL;
3463         skinframe->fog = NULL;
3464         skinframe->reflect = NULL;
3465         skinframe->hasalpha = false;
3466
3467         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3468         if (!skindata)
3469                 return NULL;
3470
3471         if (developer_loading.integer)
3472                 Con_Printf("loading quake skin \"%s\"\n", name);
3473
3474         // 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)
3475         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3476         memcpy(skinframe->qpixels, skindata, width*height);
3477         skinframe->qwidth = width;
3478         skinframe->qheight = height;
3479
3480         featuresmask = 0;
3481         for (i = 0;i < width * height;i++)
3482                 featuresmask |= palette_featureflags[skindata[i]];
3483
3484         skinframe->hasalpha = false;
3485         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3486         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3487         skinframe->qgeneratemerged = true;
3488         skinframe->qgeneratebase = skinframe->qhascolormapping;
3489         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3490
3491         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3492         //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]);
3493
3494         return skinframe;
3495 }
3496
3497 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3498 {
3499         int width;
3500         int height;
3501         unsigned char *skindata;
3502
3503         if (!skinframe->qpixels)
3504                 return;
3505
3506         if (!skinframe->qhascolormapping)
3507                 colormapped = false;
3508
3509         if (colormapped)
3510         {
3511                 if (!skinframe->qgeneratebase)
3512                         return;
3513         }
3514         else
3515         {
3516                 if (!skinframe->qgeneratemerged)
3517                         return;
3518         }
3519
3520         width = skinframe->qwidth;
3521         height = skinframe->qheight;
3522         skindata = skinframe->qpixels;
3523
3524         if (skinframe->qgeneratenmap)
3525         {
3526                 unsigned char *temp1, *temp2;
3527                 skinframe->qgeneratenmap = false;
3528                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3529                 temp2 = temp1 + width * height * 4;
3530                 // use either a custom palette or the quake palette
3531                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3532                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533                 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);
3534                 Mem_Free(temp1);
3535         }
3536
3537         if (skinframe->qgenerateglow)
3538         {
3539                 skinframe->qgenerateglow = false;
3540                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3541         }
3542
3543         if (colormapped)
3544         {
3545                 skinframe->qgeneratebase = false;
3546                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3547                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3548                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3549         }
3550         else
3551         {
3552                 skinframe->qgeneratemerged = false;
3553                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3554         }
3555
3556         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3557         {
3558                 Mem_Free(skinframe->qpixels);
3559                 skinframe->qpixels = NULL;
3560         }
3561 }
3562
3563 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)
3564 {
3565         int i;
3566         skinframe_t *skinframe;
3567
3568         if (cls.state == ca_dedicated)
3569                 return NULL;
3570
3571         // if already loaded just return it, otherwise make a new skinframe
3572         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3573         if (skinframe && skinframe->base)
3574                 return skinframe;
3575
3576         skinframe->stain = NULL;
3577         skinframe->merged = NULL;
3578         skinframe->base = NULL;
3579         skinframe->pants = NULL;
3580         skinframe->shirt = NULL;
3581         skinframe->nmap = NULL;
3582         skinframe->gloss = NULL;
3583         skinframe->glow = NULL;
3584         skinframe->fog = NULL;
3585         skinframe->reflect = NULL;
3586         skinframe->hasalpha = false;
3587
3588         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3589         if (!skindata)
3590                 return NULL;
3591
3592         if (developer_loading.integer)
3593                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3594
3595         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3596         if (textureflags & TEXF_ALPHA)
3597         {
3598                 for (i = 0;i < width * height;i++)
3599                 {
3600                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3601                         {
3602                                 skinframe->hasalpha = true;
3603                                 break;
3604                         }
3605                 }
3606                 if (r_loadfog && skinframe->hasalpha)
3607                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3608         }
3609
3610         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3611         //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]);
3612
3613         return skinframe;
3614 }
3615
3616 skinframe_t *R_SkinFrame_LoadMissing(void)
3617 {
3618         skinframe_t *skinframe;
3619
3620         if (cls.state == ca_dedicated)
3621                 return NULL;
3622
3623         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3624         skinframe->stain = NULL;
3625         skinframe->merged = NULL;
3626         skinframe->base = NULL;
3627         skinframe->pants = NULL;
3628         skinframe->shirt = NULL;
3629         skinframe->nmap = NULL;
3630         skinframe->gloss = NULL;
3631         skinframe->glow = NULL;
3632         skinframe->fog = NULL;
3633         skinframe->reflect = NULL;
3634         skinframe->hasalpha = false;
3635
3636         skinframe->avgcolor[0] = rand() / RAND_MAX;
3637         skinframe->avgcolor[1] = rand() / RAND_MAX;
3638         skinframe->avgcolor[2] = rand() / RAND_MAX;
3639         skinframe->avgcolor[3] = 1;
3640
3641         return skinframe;
3642 }
3643
3644 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3645 typedef struct suffixinfo_s
3646 {
3647         const char *suffix;
3648         qboolean flipx, flipy, flipdiagonal;
3649 }
3650 suffixinfo_t;
3651 static suffixinfo_t suffix[3][6] =
3652 {
3653         {
3654                 {"px",   false, false, false},
3655                 {"nx",   false, false, false},
3656                 {"py",   false, false, false},
3657                 {"ny",   false, false, false},
3658                 {"pz",   false, false, false},
3659                 {"nz",   false, false, false}
3660         },
3661         {
3662                 {"posx", false, false, false},
3663                 {"negx", false, false, false},
3664                 {"posy", false, false, false},
3665                 {"negy", false, false, false},
3666                 {"posz", false, false, false},
3667                 {"negz", false, false, false}
3668         },
3669         {
3670                 {"rt",    true, false,  true},
3671                 {"lf",   false,  true,  true},
3672                 {"ft",    true,  true, false},
3673                 {"bk",   false, false, false},
3674                 {"up",    true, false,  true},
3675                 {"dn",    true, false,  true}
3676         }
3677 };
3678
3679 static int componentorder[4] = {0, 1, 2, 3};
3680
3681 rtexture_t *R_LoadCubemap(const char *basename)
3682 {
3683         int i, j, cubemapsize;
3684         unsigned char *cubemappixels, *image_buffer;
3685         rtexture_t *cubemaptexture;
3686         char name[256];
3687         // must start 0 so the first loadimagepixels has no requested width/height
3688         cubemapsize = 0;
3689         cubemappixels = NULL;
3690         cubemaptexture = NULL;
3691         // keep trying different suffix groups (posx, px, rt) until one loads
3692         for (j = 0;j < 3 && !cubemappixels;j++)
3693         {
3694                 // load the 6 images in the suffix group
3695                 for (i = 0;i < 6;i++)
3696                 {
3697                         // generate an image name based on the base and and suffix
3698                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3699                         // load it
3700                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3701                         {
3702                                 // an image loaded, make sure width and height are equal
3703                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3704                                 {
3705                                         // if this is the first image to load successfully, allocate the cubemap memory
3706                                         if (!cubemappixels && image_width >= 1)
3707                                         {
3708                                                 cubemapsize = image_width;
3709                                                 // note this clears to black, so unavailable sides are black
3710                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3711                                         }
3712                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3713                                         if (cubemappixels)
3714                                                 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);
3715                                 }
3716                                 else
3717                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3718                                 // free the image
3719                                 Mem_Free(image_buffer);
3720                         }
3721                 }
3722         }
3723         // if a cubemap loaded, upload it
3724         if (cubemappixels)
3725         {
3726                 if (developer_loading.integer)
3727                         Con_Printf("loading cubemap \"%s\"\n", basename);
3728
3729                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3730                 Mem_Free(cubemappixels);
3731         }
3732         else
3733         {
3734                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3735                 if (developer_loading.integer)
3736                 {
3737                         Con_Printf("(tried tried images ");
3738                         for (j = 0;j < 3;j++)
3739                                 for (i = 0;i < 6;i++)
3740                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3741                         Con_Print(" and was unable to find any of them).\n");
3742                 }
3743         }
3744         return cubemaptexture;
3745 }
3746
3747 rtexture_t *R_GetCubemap(const char *basename)
3748 {
3749         int i;
3750         for (i = 0;i < r_texture_numcubemaps;i++)
3751                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3752                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3753         if (i >= MAX_CUBEMAPS)
3754                 return r_texture_whitecube;
3755         r_texture_numcubemaps++;
3756         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3757         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3758         return r_texture_cubemaps[i].texture;
3759 }
3760
3761 void R_FreeCubemaps(void)
3762 {
3763         int i;
3764         for (i = 0;i < r_texture_numcubemaps;i++)
3765         {
3766                 if (developer_loading.integer)
3767                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3768                 if (r_texture_cubemaps[i].texture)
3769                         R_FreeTexture(r_texture_cubemaps[i].texture);
3770         }
3771         r_texture_numcubemaps = 0;
3772 }
3773
3774 void R_Main_FreeViewCache(void)
3775 {
3776         if (r_refdef.viewcache.entityvisible)
3777                 Mem_Free(r_refdef.viewcache.entityvisible);
3778         if (r_refdef.viewcache.world_pvsbits)
3779                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3780         if (r_refdef.viewcache.world_leafvisible)
3781                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3782         if (r_refdef.viewcache.world_surfacevisible)
3783                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3784         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3785 }
3786
3787 void R_Main_ResizeViewCache(void)
3788 {
3789         int numentities = r_refdef.scene.numentities;
3790         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3791         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3792         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3793         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3794         if (r_refdef.viewcache.maxentities < numentities)
3795         {
3796                 r_refdef.viewcache.maxentities = numentities;
3797                 if (r_refdef.viewcache.entityvisible)
3798                         Mem_Free(r_refdef.viewcache.entityvisible);
3799                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3800         }
3801         if (r_refdef.viewcache.world_numclusters != numclusters)
3802         {
3803                 r_refdef.viewcache.world_numclusters = numclusters;
3804                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3805                 if (r_refdef.viewcache.world_pvsbits)
3806                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3807                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3808         }
3809         if (r_refdef.viewcache.world_numleafs != numleafs)
3810         {
3811                 r_refdef.viewcache.world_numleafs = numleafs;
3812                 if (r_refdef.viewcache.world_leafvisible)
3813                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3814                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3815         }
3816         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3817         {
3818                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3819                 if (r_refdef.viewcache.world_surfacevisible)
3820                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3822         }
3823 }
3824
3825 extern rtexture_t *loadingscreentexture;
3826 void gl_main_start(void)
3827 {
3828         loadingscreentexture = NULL;
3829         r_texture_blanknormalmap = NULL;
3830         r_texture_white = NULL;
3831         r_texture_grey128 = NULL;
3832         r_texture_black = NULL;
3833         r_texture_whitecube = NULL;
3834         r_texture_normalizationcube = NULL;
3835         r_texture_fogattenuation = NULL;
3836         r_texture_fogheighttexture = NULL;
3837         r_texture_gammaramps = NULL;
3838         r_texture_numcubemaps = 0;
3839
3840         r_loaddds = r_texture_dds_load.integer != 0;
3841         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3842
3843         switch(vid.renderpath)
3844         {
3845         case RENDERPATH_GL20:
3846         case RENDERPATH_D3D9:
3847         case RENDERPATH_D3D10:
3848         case RENDERPATH_D3D11:
3849         case RENDERPATH_SOFT:
3850         case RENDERPATH_GLES2:
3851                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852                 Cvar_SetValueQuick(&gl_combine, 1);
3853                 Cvar_SetValueQuick(&r_glsl, 1);
3854                 r_loadnormalmap = true;
3855                 r_loadgloss = true;
3856                 r_loadfog = false;
3857                 break;
3858         case RENDERPATH_GL13:
3859         case RENDERPATH_GLES1:
3860                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861                 Cvar_SetValueQuick(&gl_combine, 1);
3862                 Cvar_SetValueQuick(&r_glsl, 0);
3863                 r_loadnormalmap = false;
3864                 r_loadgloss = false;
3865                 r_loadfog = true;
3866                 break;
3867         case RENDERPATH_GL11:
3868                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3869                 Cvar_SetValueQuick(&gl_combine, 0);
3870                 Cvar_SetValueQuick(&r_glsl, 0);
3871                 r_loadnormalmap = false;
3872                 r_loadgloss = false;
3873                 r_loadfog = true;
3874                 break;
3875         }
3876
3877         R_AnimCache_Free();
3878         R_FrameData_Reset();
3879
3880         r_numqueries = 0;
3881         r_maxqueries = 0;
3882         memset(r_queries, 0, sizeof(r_queries));
3883
3884         r_qwskincache = NULL;
3885         r_qwskincache_size = 0;
3886
3887         // due to caching of texture_t references, the collision cache must be reset
3888         Collision_Cache_Reset(true);
3889
3890         // set up r_skinframe loading system for textures
3891         memset(&r_skinframe, 0, sizeof(r_skinframe));
3892         r_skinframe.loadsequence = 1;
3893         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3894
3895         r_main_texturepool = R_AllocTexturePool();
3896         R_BuildBlankTextures();
3897         R_BuildNoTexture();
3898         if (vid.support.arb_texture_cube_map)
3899         {
3900                 R_BuildWhiteCube();
3901                 R_BuildNormalizationCube();
3902         }
3903         r_texture_fogattenuation = NULL;
3904         r_texture_fogheighttexture = NULL;
3905         r_texture_gammaramps = NULL;
3906         //r_texture_fogintensity = NULL;
3907         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3908         memset(&r_waterstate, 0, sizeof(r_waterstate));
3909         r_glsl_permutation = NULL;
3910         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3911         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3912         glslshaderstring = NULL;
3913 #ifdef SUPPORTD3D
3914         r_hlsl_permutation = NULL;
3915         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3916         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3917 #endif
3918         hlslshaderstring = NULL;
3919         memset(&r_svbsp, 0, sizeof (r_svbsp));
3920
3921         r_refdef.fogmasktable_density = 0;
3922 }
3923
3924 void gl_main_shutdown(void)
3925 {
3926         R_AnimCache_Free();
3927         R_FrameData_Reset();
3928
3929         R_Main_FreeViewCache();
3930
3931         switch(vid.renderpath)
3932         {
3933         case RENDERPATH_GL11:
3934         case RENDERPATH_GL13:
3935         case RENDERPATH_GL20:
3936         case RENDERPATH_GLES1:
3937         case RENDERPATH_GLES2:
3938                 if (r_maxqueries)
3939                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3940                 break;
3941         case RENDERPATH_D3D9:
3942                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3943                 break;
3944         case RENDERPATH_D3D10:
3945                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3946                 break;
3947         case RENDERPATH_D3D11:
3948                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3949                 break;
3950         case RENDERPATH_SOFT:
3951                 break;
3952         }
3953
3954         r_numqueries = 0;
3955         r_maxqueries = 0;
3956         memset(r_queries, 0, sizeof(r_queries));
3957
3958         r_qwskincache = NULL;
3959         r_qwskincache_size = 0;
3960
3961         // clear out the r_skinframe state
3962         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3963         memset(&r_skinframe, 0, sizeof(r_skinframe));
3964
3965         if (r_svbsp.nodes)
3966                 Mem_Free(r_svbsp.nodes);
3967         memset(&r_svbsp, 0, sizeof (r_svbsp));
3968         R_FreeTexturePool(&r_main_texturepool);
3969         loadingscreentexture = NULL;
3970         r_texture_blanknormalmap = NULL;
3971         r_texture_white = NULL;
3972         r_texture_grey128 = NULL;
3973         r_texture_black = NULL;
3974         r_texture_whitecube = NULL;
3975         r_texture_normalizationcube = NULL;
3976         r_texture_fogattenuation = NULL;
3977         r_texture_fogheighttexture = NULL;
3978         r_texture_gammaramps = NULL;
3979         r_texture_numcubemaps = 0;
3980         //r_texture_fogintensity = NULL;
3981         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3982         memset(&r_waterstate, 0, sizeof(r_waterstate));
3983         R_GLSL_Restart_f();
3984
3985         r_glsl_permutation = NULL;
3986         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3987         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3988         glslshaderstring = NULL;
3989 #ifdef SUPPORTD3D
3990         r_hlsl_permutation = NULL;
3991         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3992         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3993 #endif
3994         hlslshaderstring = NULL;
3995 }
3996
3997 extern void CL_ParseEntityLump(char *entitystring);
3998 void gl_main_newmap(void)
3999 {
4000         // FIXME: move this code to client
4001         char *entities, entname[MAX_QPATH];
4002         if (r_qwskincache)
4003                 Mem_Free(r_qwskincache);
4004         r_qwskincache = NULL;
4005         r_qwskincache_size = 0;
4006         if (cl.worldmodel)
4007         {
4008                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4009                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4010                 {
4011                         CL_ParseEntityLump(entities);
4012                         Mem_Free(entities);
4013                         return;
4014                 }
4015                 if (cl.worldmodel->brush.entities)
4016                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4017         }
4018         R_Main_FreeViewCache();
4019
4020         R_FrameData_Reset();
4021 }
4022
4023 void GL_Main_Init(void)
4024 {
4025         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4026
4027         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4028         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4029         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4030         if (gamemode == GAME_NEHAHRA)
4031         {
4032                 Cvar_RegisterVariable (&gl_fogenable);
4033                 Cvar_RegisterVariable (&gl_fogdensity);
4034                 Cvar_RegisterVariable (&gl_fogred);
4035                 Cvar_RegisterVariable (&gl_foggreen);
4036                 Cvar_RegisterVariable (&gl_fogblue);
4037                 Cvar_RegisterVariable (&gl_fogstart);
4038                 Cvar_RegisterVariable (&gl_fogend);
4039                 Cvar_RegisterVariable (&gl_skyclip);
4040         }
4041         Cvar_RegisterVariable(&r_motionblur);
4042         Cvar_RegisterVariable(&r_motionblur_maxblur);
4043         Cvar_RegisterVariable(&r_motionblur_bmin);
4044         Cvar_RegisterVariable(&r_motionblur_vmin);
4045         Cvar_RegisterVariable(&r_motionblur_vmax);
4046         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4047         Cvar_RegisterVariable(&r_motionblur_randomize);
4048         Cvar_RegisterVariable(&r_damageblur);
4049         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4050         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4051         Cvar_RegisterVariable(&r_equalize_entities_by);
4052         Cvar_RegisterVariable(&r_equalize_entities_to);
4053         Cvar_RegisterVariable(&r_depthfirst);
4054         Cvar_RegisterVariable(&r_useinfinitefarclip);
4055         Cvar_RegisterVariable(&r_farclip_base);
4056         Cvar_RegisterVariable(&r_farclip_world);
4057         Cvar_RegisterVariable(&r_nearclip);
4058         Cvar_RegisterVariable(&r_deformvertexes);
4059         Cvar_RegisterVariable(&r_transparent);
4060         Cvar_RegisterVariable(&r_showoverdraw);
4061         Cvar_RegisterVariable(&r_showbboxes);
4062         Cvar_RegisterVariable(&r_showsurfaces);
4063         Cvar_RegisterVariable(&r_showtris);
4064         Cvar_RegisterVariable(&r_shownormals);
4065         Cvar_RegisterVariable(&r_showlighting);
4066         Cvar_RegisterVariable(&r_showshadowvolumes);
4067         Cvar_RegisterVariable(&r_showcollisionbrushes);
4068         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4069         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4070         Cvar_RegisterVariable(&r_showdisabledepthtest);
4071         Cvar_RegisterVariable(&r_drawportals);
4072         Cvar_RegisterVariable(&r_drawentities);
4073         Cvar_RegisterVariable(&r_draw2d);
4074         Cvar_RegisterVariable(&r_drawworld);
4075         Cvar_RegisterVariable(&r_cullentities_trace);
4076         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4077         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4078         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4079         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4080         Cvar_RegisterVariable(&r_drawviewmodel);
4081         Cvar_RegisterVariable(&r_drawexteriormodel);
4082         Cvar_RegisterVariable(&r_speeds);
4083         Cvar_RegisterVariable(&r_fullbrights);
4084         Cvar_RegisterVariable(&r_wateralpha);
4085         Cvar_RegisterVariable(&r_dynamic);
4086         Cvar_RegisterVariable(&r_fakelight);
4087         Cvar_RegisterVariable(&r_fakelight_intensity);
4088         Cvar_RegisterVariable(&r_fullbright);
4089         Cvar_RegisterVariable(&r_shadows);
4090         Cvar_RegisterVariable(&r_shadows_darken);
4091         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4092         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4093         Cvar_RegisterVariable(&r_shadows_throwdistance);
4094         Cvar_RegisterVariable(&r_shadows_throwdirection);
4095         Cvar_RegisterVariable(&r_shadows_focus);
4096         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4097         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4098         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4099         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4100         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4101         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4102         Cvar_RegisterVariable(&r_fog_exp2);
4103         Cvar_RegisterVariable(&r_fog_clear);
4104         Cvar_RegisterVariable(&r_drawfog);
4105         Cvar_RegisterVariable(&r_transparentdepthmasking);
4106         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4107         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4108         Cvar_RegisterVariable(&r_texture_dds_load);
4109         Cvar_RegisterVariable(&r_texture_dds_save);
4110         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4111         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4112         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4113         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4114         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4115         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4116         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4117         Cvar_RegisterVariable(&r_textureunits);
4118         Cvar_RegisterVariable(&gl_combine);
4119         Cvar_RegisterVariable(&r_viewfbo);
4120         Cvar_RegisterVariable(&r_viewscale);
4121         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127         Cvar_RegisterVariable(&r_glsl);
4128         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135         Cvar_RegisterVariable(&r_glsl_postprocess);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4144
4145         Cvar_RegisterVariable(&r_water);
4146         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147         Cvar_RegisterVariable(&r_water_clippingplanebias);
4148         Cvar_RegisterVariable(&r_water_refractdistort);
4149         Cvar_RegisterVariable(&r_water_reflectdistort);
4150         Cvar_RegisterVariable(&r_water_scissormode);
4151         Cvar_RegisterVariable(&r_lerpsprites);
4152         Cvar_RegisterVariable(&r_lerpmodels);
4153         Cvar_RegisterVariable(&r_lerplightstyles);
4154         Cvar_RegisterVariable(&r_waterscroll);
4155         Cvar_RegisterVariable(&r_bloom);
4156         Cvar_RegisterVariable(&r_bloom_colorscale);
4157         Cvar_RegisterVariable(&r_bloom_brighten);
4158         Cvar_RegisterVariable(&r_bloom_blur);
4159         Cvar_RegisterVariable(&r_bloom_resolution);
4160         Cvar_RegisterVariable(&r_bloom_colorexponent);
4161         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162         Cvar_RegisterVariable(&r_hdr);
4163         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164         Cvar_RegisterVariable(&r_hdr_glowintensity);
4165         Cvar_RegisterVariable(&r_hdr_range);
4166         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173         Cvar_RegisterVariable(&developer_texturelogging);
4174         Cvar_RegisterVariable(&gl_lightmaps);
4175         Cvar_RegisterVariable(&r_test);
4176         Cvar_RegisterVariable(&r_glsl_saturation);
4177         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179         Cvar_RegisterVariable(&r_framedatasize);
4180         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181                 Cvar_SetValue("r_fullbrights", 0);
4182         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4183
4184         Cvar_RegisterVariable(&r_track_sprites);
4185         Cvar_RegisterVariable(&r_track_sprites_flags);
4186         Cvar_RegisterVariable(&r_track_sprites_scalew);
4187         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4192 }
4193
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4207
4208 void Render_Init(void)
4209 {
4210         gl_backend_init();
4211         R_Textures_Init();
4212         GL_Main_Init();
4213         Font_Init();
4214         GL_Draw_Init();
4215         R_Shadow_Init();
4216         R_Sky_Init();
4217         GL_Surf_Init();
4218         Sbar_Init();
4219         R_Particles_Init();
4220         R_Explosion_Init();
4221         R_LightningBeams_Init();
4222         Mod_RenderInit();
4223 }
4224
4225 /*
4226 ===============
4227 GL_Init
4228 ===============
4229 */
4230 extern char *ENGINE_EXTENSIONS;
4231 void GL_Init (void)
4232 {
4233         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235         gl_version = (const char *)qglGetString(GL_VERSION);
4236         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4237
4238         if (!gl_extensions)
4239                 gl_extensions = "";
4240         if (!gl_platformextensions)
4241                 gl_platformextensions = "";
4242
4243         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245         Con_Printf("GL_VERSION: %s\n", gl_version);
4246         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4248
4249         VID_CheckExtensions();
4250
4251         // LordHavoc: report supported extensions
4252         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4253
4254         // clear to black (loading plaque will be seen over this)
4255         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4256 }
4257
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4259 {
4260         int i;
4261         mplane_t *p;
4262         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4263         {
4264                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4265                 if (i == 4)
4266                         continue;
4267                 p = r_refdef.view.frustum + i;
4268                 switch(p->signbits)
4269                 {
4270                 default:
4271                 case 0:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 1:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 2:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 3:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 4:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 5:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 6:
4296                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 7:
4300                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 }
4304         }
4305         return false;
4306 }
4307
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4309 {
4310         int i;
4311         const mplane_t *p;
4312         for (i = 0;i < numplanes;i++)
4313         {
4314                 p = planes + i;
4315                 switch(p->signbits)
4316                 {
4317                 default:
4318                 case 0:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 1:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 2:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 3:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 4:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 5:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 case 6:
4343                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4344                                 return true;
4345                         break;
4346                 case 7:
4347                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4348                                 return true;
4349                         break;
4350                 }
4351         }
4352         return false;
4353 }
4354
4355 //==================================================================================
4356
4357 // LordHavoc: this stores temporary data used within the same frame
4358
4359 typedef struct r_framedata_mem_s
4360 {
4361         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362         size_t size; // how much usable space
4363         size_t current; // how much space in use
4364         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365         size_t wantedsize; // how much space was allocated
4366         unsigned char *data; // start of real data (16byte aligned)
4367 }
4368 r_framedata_mem_t;
4369
4370 static r_framedata_mem_t *r_framedata_mem;
4371
4372 void R_FrameData_Reset(void)
4373 {
4374         while (r_framedata_mem)
4375         {
4376                 r_framedata_mem_t *next = r_framedata_mem->purge;
4377                 Mem_Free(r_framedata_mem);
4378                 r_framedata_mem = next;
4379         }
4380 }
4381
4382 void R_FrameData_Resize(void)
4383 {
4384         size_t wantedsize;
4385         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4388         {
4389                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390                 newmem->wantedsize = wantedsize;
4391                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393                 newmem->current = 0;
4394                 newmem->mark = 0;
4395                 newmem->purge = r_framedata_mem;
4396                 r_framedata_mem = newmem;
4397         }
4398 }
4399
4400 void R_FrameData_NewFrame(void)
4401 {
4402         R_FrameData_Resize();
4403         if (!r_framedata_mem)
4404                 return;
4405         // if we ran out of space on the last frame, free the old memory now
4406         while (r_framedata_mem->purge)
4407         {
4408                 // repeatedly remove the second item in the list, leaving only head
4409                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410                 Mem_Free(r_framedata_mem->purge);
4411                 r_framedata_mem->purge = next;
4412         }
4413         // reset the current mem pointer
4414         r_framedata_mem->current = 0;
4415         r_framedata_mem->mark = 0;
4416 }
4417
4418 void *R_FrameData_Alloc(size_t size)
4419 {
4420         void *data;
4421
4422         // align to 16 byte boundary - the data pointer is already aligned, so we
4423         // only need to ensure the size of every allocation is also aligned
4424         size = (size + 15) & ~15;
4425
4426         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4427         {
4428                 // emergency - we ran out of space, allocate more memory
4429                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430                 R_FrameData_Resize();
4431         }
4432
4433         data = r_framedata_mem->data + r_framedata_mem->current;
4434         r_framedata_mem->current += size;
4435
4436         // count the usage for stats
4437         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4439
4440         return (void *)data;
4441 }
4442
4443 void *R_FrameData_Store(size_t size, void *data)
4444 {
4445         void *d = R_FrameData_Alloc(size);
4446         if (d && data)
4447                 memcpy(d, data, size);
4448         return d;
4449 }
4450
4451 void R_FrameData_SetMark(void)
4452 {
4453         if (!r_framedata_mem)
4454                 return;
4455         r_framedata_mem->mark = r_framedata_mem->current;
4456 }
4457
4458 void R_FrameData_ReturnToMark(void)
4459 {
4460         if (!r_framedata_mem)
4461                 return;
4462         r_framedata_mem->current = r_framedata_mem->mark;
4463 }
4464
4465 //==================================================================================
4466
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4468
4469 /**
4470  * Animation cache prevents re-generating mesh data for an animated model
4471  * multiple times in one frame for lighting, shadowing, reflections, etc.
4472  */
4473
4474 void R_AnimCache_Free(void)
4475 {
4476 }
4477
4478 void R_AnimCache_ClearCache(void)
4479 {
4480         int i;
4481         entity_render_t *ent;
4482
4483         for (i = 0;i < r_refdef.scene.numentities;i++)
4484         {
4485                 ent = r_refdef.scene.entities[i];
4486                 ent->animcache_vertex3f = NULL;
4487                 ent->animcache_normal3f = NULL;
4488                 ent->animcache_svector3f = NULL;
4489                 ent->animcache_tvector3f = NULL;
4490                 ent->animcache_vertexmesh = NULL;
4491                 ent->animcache_vertex3fbuffer = NULL;
4492                 ent->animcache_vertexmeshbuffer = NULL;
4493         }
4494 }
4495
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4497 {
4498         int i;
4499
4500         // check if we need the meshbuffers
4501         if (!vid.useinterleavedarrays)
4502                 return;
4503
4504         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506         // TODO: upload vertex3f buffer?
4507         if (ent->animcache_vertexmesh)
4508         {
4509                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510                 for (i = 0;i < numvertices;i++)
4511                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512                 if (ent->animcache_svector3f)
4513                         for (i = 0;i < numvertices;i++)
4514                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515                 if (ent->animcache_tvector3f)
4516                         for (i = 0;i < numvertices;i++)
4517                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518                 if (ent->animcache_normal3f)
4519                         for (i = 0;i < numvertices;i++)
4520                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521                 // TODO: upload vertexmeshbuffer?
4522         }
4523 }
4524
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4526 {
4527         dp_model_t *model = ent->model;
4528         int numvertices;
4529         // see if it's already cached this frame
4530         if (ent->animcache_vertex3f)
4531         {
4532                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533                 if (wantnormals || wanttangents)
4534                 {
4535                         if (ent->animcache_normal3f)
4536                                 wantnormals = false;
4537                         if (ent->animcache_svector3f)
4538                                 wanttangents = false;
4539                         if (wantnormals || wanttangents)
4540                         {
4541                                 numvertices = model->surfmesh.num_vertices;
4542                                 if (wantnormals)
4543                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544                                 if (wanttangents)
4545                                 {
4546                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548                                 }
4549                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4551                         }
4552                 }
4553         }
4554         else
4555         {
4556                 // see if this ent is worth caching
4557                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4558                         return false;
4559                 // get some memory for this entity and generate mesh data
4560                 numvertices = model->surfmesh.num_vertices;
4561                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4562                 if (wantnormals)
4563                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 if (wanttangents)
4565                 {
4566                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4568                 }
4569                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4571         }
4572         return true;
4573 }
4574
4575 void R_AnimCache_CacheVisibleEntities(void)
4576 {
4577         int i;
4578         qboolean wantnormals = true;
4579         qboolean wanttangents = !r_showsurfaces.integer;
4580
4581         switch(vid.renderpath)
4582         {
4583         case RENDERPATH_GL20:
4584         case RENDERPATH_D3D9:
4585         case RENDERPATH_D3D10:
4586         case RENDERPATH_D3D11:
4587         case RENDERPATH_GLES2:
4588                 break;
4589         case RENDERPATH_GL11:
4590         case RENDERPATH_GL13:
4591         case RENDERPATH_GLES1:
4592                 wanttangents = false;
4593                 break;
4594         case RENDERPATH_SOFT:
4595                 break;
4596         }
4597
4598         if (r_shownormals.integer)
4599                 wanttangents = wantnormals = true;
4600
4601         // TODO: thread this
4602         // NOTE: R_PrepareRTLights() also caches entities
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605                 if (r_refdef.viewcache.entityvisible[i])
4606                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4607 }
4608
4609 //==================================================================================
4610
4611 static void R_View_UpdateEntityLighting (void)
4612 {
4613         int i;
4614         entity_render_t *ent;
4615         vec3_t tempdiffusenormal, avg;
4616         vec_t f, fa, fd, fdd;
4617         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4618
4619         for (i = 0;i < r_refdef.scene.numentities;i++)
4620         {
4621                 ent = r_refdef.scene.entities[i];
4622
4623                 // skip unseen models
4624                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4625                         continue;
4626
4627                 // skip bsp models
4628                 if (ent->model && ent->model->brush.num_leafs)
4629                 {
4630                         // TODO: use modellight for r_ambient settings on world?
4631                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4632                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4634                         continue;
4635                 }
4636
4637                 // fetch the lighting from the worldmodel data
4638                 VectorClear(ent->modellight_ambient);
4639                 VectorClear(ent->modellight_diffuse);
4640                 VectorClear(tempdiffusenormal);
4641                 if (ent->flags & RENDER_LIGHT)
4642                 {
4643                         vec3_t org;
4644                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4645
4646                         // complete lightning for lit sprites
4647                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4649                         {
4650                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4652                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4653                         }
4654                         else
4655                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4656
4657                         if(ent->flags & RENDER_EQUALIZE)
4658                         {
4659                                 // first fix up ambient lighting...
4660                                 if(r_equalize_entities_minambient.value > 0)
4661                                 {
4662                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4663                                         if(fd > 0)
4664                                         {
4665                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666                                                 if(fa < r_equalize_entities_minambient.value * fd)
4667                                                 {
4668                                                         // solve:
4669                                                         //   fa'/fd' = minambient
4670                                                         //   fa'+0.25*fd' = fa+0.25*fd
4671                                                         //   ...
4672                                                         //   fa' = fd' * minambient
4673                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4674                                                         //   ...
4675                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4677                                                         //   ...
4678                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679                                                         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
4680                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4682                                                 }
4683                                         }
4684                                 }
4685
4686                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4687                                 {
4688                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4690                                         f = fa + 0.25 * fd;
4691                                         if(f > 0)
4692                                         {
4693                                                 // adjust brightness and saturation to target
4694                                                 avg[0] = avg[1] = avg[2] = fa / f;
4695                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696                                                 avg[0] = avg[1] = avg[2] = fd / f;
4697                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4698                                         }
4699                                 }
4700                         }
4701                 }
4702                 else // highly rare
4703                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4704
4705                 // move the light direction into modelspace coordinates for lighting code
4706                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707                 if(VectorLength2(ent->modellight_lightdir) == 0)
4708                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709                 VectorNormalize(ent->modellight_lightdir);
4710         }
4711 }
4712
4713 #define MAX_LINEOFSIGHTTRACES 64
4714
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4716 {
4717         int i;
4718         vec3_t boxmins, boxmaxs;
4719         vec3_t start;
4720         vec3_t end;
4721         dp_model_t *model = r_refdef.scene.worldmodel;
4722
4723         if (!model || !model->brush.TraceLineOfSight)
4724                 return true;
4725
4726         // expand the box a little
4727         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4733
4734         // return true if eye is inside enlarged box
4735         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4736                 return true;
4737
4738         // try center
4739         VectorCopy(eye, start);
4740         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741         if (model->brush.TraceLineOfSight(model, start, end))
4742                 return true;
4743
4744         // try various random positions
4745         for (i = 0;i < numsamples;i++)
4746         {
4747                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748                 if (model->brush.TraceLineOfSight(model, start, end))
4749                         return true;
4750         }
4751
4752         return false;
4753 }
4754
4755
4756 static void R_View_UpdateEntityVisible (void)
4757 {
4758         int i;
4759         int renderimask;
4760         int samples;
4761         entity_render_t *ent;
4762
4763         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4766                 :                                                          RENDER_EXTERIORMODEL;
4767         if (!r_drawviewmodel.integer)
4768                 renderimask |= RENDER_VIEWMODEL;
4769         if (!r_drawexteriormodel.integer)
4770                 renderimask |= RENDER_EXTERIORMODEL;
4771         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4772         {
4773                 // worldmodel can check visibility
4774                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775                 for (i = 0;i < r_refdef.scene.numentities;i++)
4776                 {
4777                         ent = r_refdef.scene.entities[i];
4778                         if (!(ent->flags & renderimask))
4779                         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)))
4780                         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))
4781                                 r_refdef.viewcache.entityvisible[i] = true;
4782                 }
4783         }
4784         else
4785         {
4786                 // no worldmodel or it can't check visibility
4787                 for (i = 0;i < r_refdef.scene.numentities;i++)
4788                 {
4789                         ent = r_refdef.scene.entities[i];
4790                         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));
4791                 }
4792         }
4793         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4795         {
4796                 for (i = 0;i < r_refdef.scene.numentities;i++)
4797                 {
4798                         if (!r_refdef.viewcache.entityvisible[i])
4799                                 continue;
4800                         ent = r_refdef.scene.entities[i];
4801                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4802                         {
4803                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4804                                 if (samples < 0)
4805                                         continue; // temp entities do pvs only
4806                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807                                         ent->last_trace_visibility = realtime;
4808                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809                                         r_refdef.viewcache.entityvisible[i] = 0;
4810                         }
4811                 }
4812         }
4813 }
4814
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4817 {
4818         int i, sky;
4819         entity_render_t *ent;
4820
4821         sky = false;
4822         for (i = 0;i < r_refdef.scene.numentities;i++)
4823         {
4824                 if (!r_refdef.viewcache.entityvisible[i])
4825                         continue;
4826                 ent = r_refdef.scene.entities[i];
4827                 if (!ent->model || !ent->model->DrawSky)
4828                         continue;
4829                 ent->model->DrawSky(ent);
4830                 sky = true;
4831         }
4832         return sky;
4833 }
4834
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4837 {
4838         int i;
4839         entity_render_t *ent;
4840
4841         for (i = 0;i < r_refdef.scene.numentities;i++)
4842         {
4843                 if (!r_refdef.viewcache.entityvisible[i])
4844                         continue;
4845                 ent = r_refdef.scene.entities[i];
4846                 r_refdef.stats.entities++;
4847                 if (ent->model && ent->model->Draw != NULL)
4848                         ent->model->Draw(ent);
4849                 else
4850                         R_DrawNoModel(ent);
4851         }
4852 }
4853
4854 static void R_DrawModelsDepth(void)
4855 {
4856         int i;
4857         entity_render_t *ent;
4858
4859         for (i = 0;i < r_refdef.scene.numentities;i++)
4860         {
4861                 if (!r_refdef.viewcache.entityvisible[i])
4862                         continue;
4863                 ent = r_refdef.scene.entities[i];
4864                 if (ent->model && ent->model->DrawDepth != NULL)
4865                         ent->model->DrawDepth(ent);
4866         }
4867 }
4868
4869 static void R_DrawModelsDebug(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 if (!r_refdef.viewcache.entityvisible[i])
4877                         continue;
4878                 ent = r_refdef.scene.entities[i];
4879                 if (ent->model && ent->model->DrawDebug != NULL)
4880                         ent->model->DrawDebug(ent);
4881         }
4882 }
4883
4884 static void R_DrawModelsAddWaterPlanes(void)
4885 {
4886         int i;
4887         entity_render_t *ent;
4888
4889         for (i = 0;i < r_refdef.scene.numentities;i++)
4890         {
4891                 if (!r_refdef.viewcache.entityvisible[i])
4892                         continue;
4893                 ent = r_refdef.scene.entities[i];
4894                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4895                         ent->model->DrawAddWaterPlanes(ent);
4896         }
4897 }
4898
4899 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4900 {
4901         if (r_hdr_irisadaptation.integer)
4902         {
4903                 vec3_t ambient;
4904                 vec3_t diffuse;
4905                 vec3_t diffusenormal;
4906                 vec_t brightness;
4907                 vec_t goal;
4908                 vec_t adjust;
4909                 vec_t current;
4910                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4911                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4912                 brightness = max(0.0000001f, brightness);
4913                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4914                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4915                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4916                 current = r_hdr_irisadaptation_value.value;
4917                 if (current < goal)
4918                         current = min(current + adjust, goal);
4919                 else if (current > goal)
4920                         current = max(current - adjust, goal);
4921                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4922                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4923         }
4924         else if (r_hdr_irisadaptation_value.value != 1.0f)
4925                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4926 }
4927
4928 static void R_View_SetFrustum(const int *scissor)
4929 {
4930         int i;
4931         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4932         vec3_t forward, left, up, origin, v;
4933
4934         if(scissor)
4935         {
4936                 // flipped x coordinates (because x points left here)
4937                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4938                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4939
4940                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4941                 switch(vid.renderpath)
4942                 {
4943                         case RENDERPATH_D3D9:
4944                         case RENDERPATH_D3D10:
4945                         case RENDERPATH_D3D11:
4946                                 // non-flipped y coordinates
4947                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4948                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4949                                 break;
4950                         case RENDERPATH_SOFT:
4951                         case RENDERPATH_GL11:
4952                         case RENDERPATH_GL13:
4953                         case RENDERPATH_GL20:
4954                         case RENDERPATH_GLES1:
4955                         case RENDERPATH_GLES2:
4956                                 // non-flipped y coordinates
4957                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4958                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959                                 break;
4960                 }
4961         }
4962
4963         // we can't trust r_refdef.view.forward and friends in reflected scenes
4964         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4965
4966 #if 0
4967         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4968         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4969         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4970         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4971         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4972         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4973         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4974         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4975         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4976         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4977         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4978         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4979 #endif
4980
4981 #if 0
4982         zNear = r_refdef.nearclip;
4983         nudge = 1.0 - 1.0 / (1<<23);
4984         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4985         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4986         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4987         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4988         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4989         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4990         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4991         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4992 #endif
4993
4994
4995
4996 #if 0
4997         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4998         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4999         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5000         r_refdef.view.frustum[0].dist = m[15] - m[12];
5001
5002         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5003         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5004         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5005         r_refdef.view.frustum[1].dist = m[15] + m[12];
5006
5007         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5008         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5009         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5010         r_refdef.view.frustum[2].dist = m[15] - m[13];
5011
5012         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5013         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5014         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5015         r_refdef.view.frustum[3].dist = m[15] + m[13];
5016
5017         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5018         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5019         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5020         r_refdef.view.frustum[4].dist = m[15] - m[14];
5021
5022         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5023         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5024         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5025         r_refdef.view.frustum[5].dist = m[15] + m[14];
5026 #endif
5027
5028         if (r_refdef.view.useperspective)
5029         {
5030                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5031                 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]);
5032                 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]);
5033                 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]);
5034                 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]);
5035
5036                 // then the normals from the corners relative to origin
5037                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5038                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5039                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5040                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5041
5042                 // in a NORMAL view, forward cross left == up
5043                 // in a REFLECTED view, forward cross left == down
5044                 // so our cross products above need to be adjusted for a left handed coordinate system
5045                 CrossProduct(forward, left, v);
5046                 if(DotProduct(v, up) < 0)
5047                 {
5048                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5049                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5050                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5051                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5052                 }
5053
5054                 // Leaving those out was a mistake, those were in the old code, and they
5055                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5056                 // I couldn't reproduce it after adding those normalizations. --blub
5057                 VectorNormalize(r_refdef.view.frustum[0].normal);
5058                 VectorNormalize(r_refdef.view.frustum[1].normal);
5059                 VectorNormalize(r_refdef.view.frustum[2].normal);
5060                 VectorNormalize(r_refdef.view.frustum[3].normal);
5061
5062                 // make the corners absolute
5063                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5064                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5065                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5066                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5067
5068                 // one more normal
5069                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5070
5071                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5072                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5073                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5074                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5075                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5076         }
5077         else
5078         {
5079                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5080                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5081                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5082                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5083                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5084                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5085                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5086                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5087                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5088                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5089         }
5090         r_refdef.view.numfrustumplanes = 5;
5091
5092         if (r_refdef.view.useclipplane)
5093         {
5094                 r_refdef.view.numfrustumplanes = 6;
5095                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5096         }
5097
5098         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5099                 PlaneClassify(r_refdef.view.frustum + i);
5100
5101         // LordHavoc: note to all quake engine coders, Quake had a special case
5102         // for 90 degrees which assumed a square view (wrong), so I removed it,
5103         // Quake2 has it disabled as well.
5104
5105         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5106         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5107         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5108         //PlaneClassify(&frustum[0]);
5109
5110         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5111         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5112         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5113         //PlaneClassify(&frustum[1]);
5114
5115         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5116         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5117         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5118         //PlaneClassify(&frustum[2]);
5119
5120         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5121         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5122         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5123         //PlaneClassify(&frustum[3]);
5124
5125         // nearclip plane
5126         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5127         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5128         //PlaneClassify(&frustum[4]);
5129 }
5130
5131 void R_View_UpdateWithScissor(const int *myscissor)
5132 {
5133         R_Main_ResizeViewCache();
5134         R_View_SetFrustum(myscissor);
5135         R_View_WorldVisibility(r_refdef.view.useclipplane);
5136         R_View_UpdateEntityVisible();
5137         R_View_UpdateEntityLighting();
5138 }
5139
5140 void R_View_Update(void)
5141 {
5142         R_Main_ResizeViewCache();
5143         R_View_SetFrustum(NULL);
5144         R_View_WorldVisibility(r_refdef.view.useclipplane);
5145         R_View_UpdateEntityVisible();
5146         R_View_UpdateEntityLighting();
5147 }
5148
5149 float viewscalefpsadjusted = 1.0f;
5150
5151 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5152 {
5153         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5154         scale = bound(0.03125f, scale, 1.0f);
5155         *outwidth = (int)ceil(width * scale);
5156         *outheight = (int)ceil(height * scale);
5157 }
5158
5159 void R_Mesh_SetMainRenderTargets(void)
5160 {
5161         if (r_bloomstate.fbo_framebuffer)
5162                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5163         else
5164                 R_Mesh_ResetRenderTargets();
5165 }
5166
5167 void R_SetupView(qboolean allowwaterclippingplane)
5168 {
5169         const float *customclipplane = NULL;
5170         float plane[4];
5171         int scaledwidth, scaledheight;
5172         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5173         {
5174                 // LordHavoc: couldn't figure out how to make this approach the
5175                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5176                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5177                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5178                         dist = r_refdef.view.clipplane.dist;
5179                 plane[0] = r_refdef.view.clipplane.normal[0];
5180                 plane[1] = r_refdef.view.clipplane.normal[1];
5181                 plane[2] = r_refdef.view.clipplane.normal[2];
5182                 plane[3] = -dist;
5183                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5184         }
5185
5186         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5187         if (!r_refdef.view.useperspective)
5188                 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);
5189         else if (vid.stencil && r_useinfinitefarclip.integer)
5190                 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);
5191         else
5192                 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);
5193         R_Mesh_SetMainRenderTargets();
5194         R_SetViewport(&r_refdef.view.viewport);
5195         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5196         {
5197                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5198                 float screenplane[4];
5199                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5200                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5201                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5202                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5203                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5204         }
5205 }
5206
5207 void R_EntityMatrix(const matrix4x4_t *matrix)
5208 {
5209         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5210         {
5211                 gl_modelmatrixchanged = false;
5212                 gl_modelmatrix = *matrix;
5213                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5214                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5215                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5216                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5217                 CHECKGLERROR
5218                 switch(vid.renderpath)
5219                 {
5220                 case RENDERPATH_D3D9:
5221 #ifdef SUPPORTD3D
5222                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5223                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5224 #endif
5225                         break;
5226                 case RENDERPATH_D3D10:
5227                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5228                         break;
5229                 case RENDERPATH_D3D11:
5230                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5231                         break;
5232                 case RENDERPATH_GL11:
5233                 case RENDERPATH_GL13:
5234                 case RENDERPATH_GLES1:
5235                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5236                         break;
5237                 case RENDERPATH_SOFT:
5238                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5239                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5240                         break;
5241                 case RENDERPATH_GL20:
5242                 case RENDERPATH_GLES2:
5243                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5244                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5245                         break;
5246                 }
5247         }
5248 }
5249
5250 void R_ResetViewRendering2D(void)
5251 {
5252         r_viewport_t viewport;
5253         DrawQ_Finish();
5254
5255         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5256         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);
5257         R_Mesh_ResetRenderTargets();
5258         R_SetViewport(&viewport);
5259         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5260         GL_Color(1, 1, 1, 1);
5261         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5262         GL_BlendFunc(GL_ONE, GL_ZERO);
5263         GL_ScissorTest(false);
5264         GL_DepthMask(false);
5265         GL_DepthRange(0, 1);
5266         GL_DepthTest(false);
5267         GL_DepthFunc(GL_LEQUAL);
5268         R_EntityMatrix(&identitymatrix);
5269         R_Mesh_ResetTextureState();
5270         GL_PolygonOffset(0, 0);
5271         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5272         switch(vid.renderpath)
5273         {
5274         case RENDERPATH_GL11:
5275         case RENDERPATH_GL13:
5276         case RENDERPATH_GL20:
5277         case RENDERPATH_GLES1:
5278         case RENDERPATH_GLES2:
5279                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5280                 break;
5281         case RENDERPATH_D3D9:
5282         case RENDERPATH_D3D10:
5283         case RENDERPATH_D3D11:
5284         case RENDERPATH_SOFT:
5285                 break;
5286         }
5287         GL_CullFace(GL_NONE);
5288 }
5289
5290 void R_ResetViewRendering3D(void)
5291 {
5292         DrawQ_Finish();
5293
5294         R_SetupView(true);
5295         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5296         GL_Color(1, 1, 1, 1);
5297         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5298         GL_BlendFunc(GL_ONE, GL_ZERO);
5299         GL_ScissorTest(true);
5300         GL_DepthMask(true);
5301         GL_DepthRange(0, 1);
5302         GL_DepthTest(true);
5303         GL_DepthFunc(GL_LEQUAL);
5304         R_EntityMatrix(&identitymatrix);
5305         R_Mesh_ResetTextureState();
5306         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5307         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5308         switch(vid.renderpath)
5309         {
5310         case RENDERPATH_GL11:
5311         case RENDERPATH_GL13:
5312         case RENDERPATH_GL20:
5313         case RENDERPATH_GLES1:
5314         case RENDERPATH_GLES2:
5315                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5316                 break;
5317         case RENDERPATH_D3D9:
5318         case RENDERPATH_D3D10:
5319         case RENDERPATH_D3D11:
5320         case RENDERPATH_SOFT:
5321                 break;
5322         }
5323         GL_CullFace(r_refdef.view.cullface_back);
5324 }
5325
5326 /*
5327 ================
5328 R_RenderView_UpdateViewVectors
5329 ================
5330 */
5331 static void R_RenderView_UpdateViewVectors(void)
5332 {
5333         // break apart the view matrix into vectors for various purposes
5334         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5335         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5336         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5337         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5338         // make an inverted copy of the view matrix for tracking sprites
5339         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5340 }
5341
5342 void R_RenderScene(void);
5343 void R_RenderWaterPlanes(void);
5344
5345 static void R_Water_StartFrame(void)
5346 {
5347         int i;
5348         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5349         r_waterstate_waterplane_t *p;
5350
5351         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5352                 return;
5353
5354         switch(vid.renderpath)
5355         {
5356         case RENDERPATH_GL20:
5357         case RENDERPATH_D3D9:
5358         case RENDERPATH_D3D10:
5359         case RENDERPATH_D3D11:
5360         case RENDERPATH_SOFT:
5361         case RENDERPATH_GLES2:
5362                 break;
5363         case RENDERPATH_GL11:
5364         case RENDERPATH_GL13:
5365         case RENDERPATH_GLES1:
5366                 return;
5367         }
5368
5369         // set waterwidth and waterheight to the water resolution that will be
5370         // used (often less than the screen resolution for faster rendering)
5371         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5372         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5373
5374         // calculate desired texture sizes
5375         // can't use water if the card does not support the texture size
5376         if (!r_water.integer || r_showsurfaces.integer)
5377                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5378         else if (vid.support.arb_texture_non_power_of_two)
5379         {
5380                 texturewidth = waterwidth;
5381                 textureheight = waterheight;
5382                 camerawidth = waterwidth;
5383                 cameraheight = waterheight;
5384         }
5385         else
5386         {
5387                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5388                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5389                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5390                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5391         }
5392
5393         // allocate textures as needed
5394         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5395         {
5396                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5397                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5398                 {
5399                         if (p->texture_refraction)
5400                                 R_FreeTexture(p->texture_refraction);
5401                         p->texture_refraction = NULL;
5402                         if (p->texture_reflection)
5403                                 R_FreeTexture(p->texture_reflection);
5404                         p->texture_reflection = NULL;
5405                         if (p->texture_camera)
5406                                 R_FreeTexture(p->texture_camera);
5407                         p->texture_camera = NULL;
5408                 }
5409                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5410                 r_waterstate.texturewidth = texturewidth;
5411                 r_waterstate.textureheight = textureheight;
5412                 r_waterstate.camerawidth = camerawidth;
5413                 r_waterstate.cameraheight = cameraheight;
5414         }
5415
5416         if (r_waterstate.texturewidth)
5417         {
5418                 r_waterstate.enabled = true;
5419
5420                 // when doing a reduced render (HDR) we want to use a smaller area
5421                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5422                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5423
5424                 // set up variables that will be used in shader setup
5425                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5426                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5427                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5428                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5429         }
5430
5431         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5432         r_waterstate.numwaterplanes = 0;
5433 }
5434
5435 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5436 {
5437         int triangleindex, planeindex;
5438         const int *e;
5439         vec3_t vert[3];
5440         vec3_t normal;
5441         vec3_t center;
5442         mplane_t plane;
5443         r_waterstate_waterplane_t *p;
5444         texture_t *t = R_GetCurrentTexture(surface->texture);
5445
5446         // just use the first triangle with a valid normal for any decisions
5447         VectorClear(normal);
5448         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5449         {
5450                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5451                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5452                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5453                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5454                 if (VectorLength2(normal) >= 0.001)
5455                         break;
5456         }
5457
5458         VectorCopy(normal, plane.normal);
5459         VectorNormalize(plane.normal);
5460         plane.dist = DotProduct(vert[0], plane.normal);
5461         PlaneClassify(&plane);
5462         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5463         {
5464                 // skip backfaces (except if nocullface is set)
5465                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5466                         return;
5467                 VectorNegate(plane.normal, plane.normal);
5468                 plane.dist *= -1;
5469                 PlaneClassify(&plane);
5470         }
5471
5472
5473         // find a matching plane if there is one
5474         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5475                 if(p->camera_entity == t->camera_entity)
5476                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5477                                 break;
5478         if (planeindex >= r_waterstate.maxwaterplanes)
5479                 return; // nothing we can do, out of planes
5480
5481         // if this triangle does not fit any known plane rendered this frame, add one
5482         if (planeindex >= r_waterstate.numwaterplanes)
5483         {
5484                 // store the new plane
5485                 r_waterstate.numwaterplanes++;
5486                 p->plane = plane;
5487                 // clear materialflags and pvs
5488                 p->materialflags = 0;
5489                 p->pvsvalid = false;
5490                 p->camera_entity = t->camera_entity;
5491                 VectorCopy(surface->mins, p->mins);
5492                 VectorCopy(surface->maxs, p->maxs);
5493         }
5494         else
5495         {
5496                 // merge mins/maxs
5497                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5498                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5499                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5500                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5501                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5502                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5503         }
5504         // merge this surface's materialflags into the waterplane
5505         p->materialflags |= t->currentmaterialflags;
5506         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5507         {
5508                 // merge this surface's PVS into the waterplane
5509                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5510                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5511                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5512                 {
5513                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5514                         p->pvsvalid = true;
5515                 }
5516         }
5517 }
5518
5519 static void R_Water_ProcessPlanes(void)
5520 {
5521         int myscissor[4];
5522         r_refdef_view_t originalview;
5523         r_refdef_view_t myview;
5524         int planeindex;
5525         r_waterstate_waterplane_t *p;
5526         vec3_t visorigin;
5527
5528         originalview = r_refdef.view;
5529
5530         // make sure enough textures are allocated
5531         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5532         {
5533                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5534                 {
5535                         if (!p->texture_refraction)
5536                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5537                         if (!p->texture_refraction)
5538                                 goto error;
5539                 }
5540                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5541                 {
5542                         if (!p->texture_camera)
5543                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5544                         if (!p->texture_camera)
5545                                 goto error;
5546                 }
5547
5548                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5549                 {
5550                         if (!p->texture_reflection)
5551                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5552                         if (!p->texture_reflection)
5553                                 goto error;
5554                 }
5555         }
5556
5557         // render views
5558         r_refdef.view = originalview;
5559         r_refdef.view.showdebug = false;
5560         r_refdef.view.width = r_waterstate.waterwidth;
5561         r_refdef.view.height = r_waterstate.waterheight;
5562         r_refdef.view.useclipplane = true;
5563         myview = r_refdef.view;
5564         r_waterstate.renderingscene = true;
5565         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5566         {
5567                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5568                 {
5569                         r_refdef.view = myview;
5570                         if(r_water_scissormode.integer)
5571                         {
5572                                 R_SetupView(true);
5573                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5575                         }
5576
5577                         // render reflected scene and copy into texture
5578                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5579                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5580                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5581                         r_refdef.view.clipplane = p->plane;
5582
5583                         // reverse the cullface settings for this render
5584                         r_refdef.view.cullface_front = GL_FRONT;
5585                         r_refdef.view.cullface_back = GL_BACK;
5586                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5587                         {
5588                                 r_refdef.view.usecustompvs = true;
5589                                 if (p->pvsvalid)
5590                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5591                                 else
5592                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5593                         }
5594
5595                         R_ResetViewRendering3D();
5596                         R_ClearScreen(r_refdef.fogenabled);
5597                         if(r_water_scissormode.integer & 2)
5598                                 R_View_UpdateWithScissor(myscissor);
5599                         else
5600                                 R_View_Update();
5601                         if(r_water_scissormode.integer & 1)
5602                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5603                         R_RenderScene();
5604
5605                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5606                 }
5607
5608                 // render the normal view scene and copy into texture
5609                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5610                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5611                 {
5612                         r_refdef.view = myview;
5613                         if(r_water_scissormode.integer)
5614                         {
5615                                 R_SetupView(true);
5616                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5617                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5618                         }
5619
5620                         r_waterstate.renderingrefraction = true;
5621
5622                         r_refdef.view.clipplane = p->plane;
5623                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5624                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5625
5626                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5627                         {
5628                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5629                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5630                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5631                                 R_RenderView_UpdateViewVectors();
5632                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5633                                 {
5634                                         r_refdef.view.usecustompvs = true;
5635                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5636                                 }
5637                         }
5638
5639                         PlaneClassify(&r_refdef.view.clipplane);
5640
5641                         R_ResetViewRendering3D();
5642                         R_ClearScreen(r_refdef.fogenabled);
5643                         if(r_water_scissormode.integer & 2)
5644                                 R_View_UpdateWithScissor(myscissor);
5645                         else
5646                                 R_View_Update();
5647                         if(r_water_scissormode.integer & 1)
5648                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5649                         R_RenderScene();
5650
5651                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5652                         r_waterstate.renderingrefraction = false;
5653                 }
5654                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5655                 {
5656                         r_refdef.view = myview;
5657
5658                         r_refdef.view.clipplane = p->plane;
5659                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5661
5662                         r_refdef.view.width = r_waterstate.camerawidth;
5663                         r_refdef.view.height = r_waterstate.cameraheight;
5664                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5665                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5666
5667                         if(p->camera_entity)
5668                         {
5669                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5670                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5671                         }
5672
5673                         // note: all of the view is used for displaying... so
5674                         // there is no use in scissoring
5675
5676                         // reverse the cullface settings for this render
5677                         r_refdef.view.cullface_front = GL_FRONT;
5678                         r_refdef.view.cullface_back = GL_BACK;
5679                         // also reverse the view matrix
5680                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5681                         R_RenderView_UpdateViewVectors();
5682                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5683                         {
5684                                 r_refdef.view.usecustompvs = true;
5685                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5686                         }
5687                         
5688                         // camera needs no clipplane
5689                         r_refdef.view.useclipplane = false;
5690
5691                         PlaneClassify(&r_refdef.view.clipplane);
5692
5693                         R_ResetViewRendering3D();
5694                         R_ClearScreen(r_refdef.fogenabled);
5695                         R_View_Update();
5696                         R_RenderScene();
5697
5698                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5699                         r_waterstate.renderingrefraction = false;
5700                 }
5701
5702         }
5703         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5704         r_waterstate.renderingscene = false;
5705         r_refdef.view = originalview;
5706         R_ResetViewRendering3D();
5707         R_ClearScreen(r_refdef.fogenabled);
5708         R_View_Update();
5709         return;
5710 error:
5711         r_refdef.view = originalview;
5712         r_waterstate.renderingscene = false;
5713         Cvar_SetValueQuick(&r_water, 0);
5714         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5715         return;
5716 }
5717
5718 void R_Bloom_StartFrame(void)
5719 {
5720         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5721         int viewwidth, viewheight;
5722         textype_t textype;
5723
5724         if (r_viewscale_fpsscaling.integer)
5725         {
5726                 double actualframetime;
5727                 double targetframetime;
5728                 double adjust;
5729                 actualframetime = r_refdef.lastdrawscreentime;
5730                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5731                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5732                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5733                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5734                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5735                 viewscalefpsadjusted += adjust;
5736                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5737         }
5738         else
5739                 viewscalefpsadjusted = 1.0f;
5740
5741         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5742
5743         switch(vid.renderpath)
5744         {
5745         case RENDERPATH_GL20:
5746         case RENDERPATH_D3D9:
5747         case RENDERPATH_D3D10:
5748         case RENDERPATH_D3D11:
5749         case RENDERPATH_SOFT:
5750         case RENDERPATH_GLES2:
5751                 break;
5752         case RENDERPATH_GL11:
5753         case RENDERPATH_GL13:
5754         case RENDERPATH_GLES1:
5755                 return;
5756         }
5757
5758         // set bloomwidth and bloomheight to the bloom resolution that will be
5759         // used (often less than the screen resolution for faster rendering)
5760         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5761         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5762         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5763         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5764         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5765
5766         // calculate desired texture sizes
5767         if (vid.support.arb_texture_non_power_of_two)
5768         {
5769                 screentexturewidth = vid.width;
5770                 screentextureheight = vid.height;
5771                 bloomtexturewidth = r_bloomstate.bloomwidth;
5772                 bloomtextureheight = r_bloomstate.bloomheight;
5773         }
5774         else
5775         {
5776                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5777                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5778                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5779                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5780         }
5781
5782         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5783         {
5784                 Cvar_SetValueQuick(&r_hdr, 0);
5785                 Cvar_SetValueQuick(&r_bloom, 0);
5786                 Cvar_SetValueQuick(&r_motionblur, 0);
5787                 Cvar_SetValueQuick(&r_damageblur, 0);
5788         }
5789
5790         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5791                 screentexturewidth = screentextureheight = 0;
5792         if (!r_hdr.integer && !r_bloom.integer)
5793                 bloomtexturewidth = bloomtextureheight = 0;
5794
5795         textype = TEXTYPE_COLORBUFFER;
5796         switch (vid.renderpath)
5797         {
5798         case RENDERPATH_GL20:
5799         case RENDERPATH_GLES2:
5800                 if (vid.support.ext_framebuffer_object)
5801                 {
5802                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5803                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5804                 }
5805                 break;
5806         case RENDERPATH_GL11:
5807         case RENDERPATH_GL13:
5808         case RENDERPATH_GLES1:
5809         case RENDERPATH_D3D9:
5810         case RENDERPATH_D3D10:
5811         case RENDERPATH_D3D11:
5812         case RENDERPATH_SOFT:
5813                 break;
5814         }
5815
5816         // allocate textures as needed
5817         if (r_bloomstate.screentexturewidth != screentexturewidth
5818          || r_bloomstate.screentextureheight != screentextureheight
5819          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5820          || r_bloomstate.bloomtextureheight != bloomtextureheight
5821          || r_bloomstate.texturetype != textype
5822          || r_bloomstate.viewfbo != r_viewfbo.integer)
5823         {
5824                 if (r_bloomstate.texture_bloom)
5825                         R_FreeTexture(r_bloomstate.texture_bloom);
5826                 r_bloomstate.texture_bloom = NULL;
5827                 if (r_bloomstate.texture_screen)
5828                         R_FreeTexture(r_bloomstate.texture_screen);
5829                 r_bloomstate.texture_screen = NULL;
5830                 if (r_bloomstate.fbo_framebuffer)
5831                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5832                 r_bloomstate.fbo_framebuffer = 0;
5833                 if (r_bloomstate.texture_framebuffercolor)
5834                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5835                 r_bloomstate.texture_framebuffercolor = NULL;
5836                 if (r_bloomstate.texture_framebufferdepth)
5837                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5838                 r_bloomstate.texture_framebufferdepth = NULL;
5839                 r_bloomstate.screentexturewidth = screentexturewidth;
5840                 r_bloomstate.screentextureheight = screentextureheight;
5841                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5842                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5843                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5844                 {
5845                         // FIXME: choose depth bits based on a cvar
5846                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5847                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5848                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5849                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5850                         // render depth into one texture and normalmap into the other
5851                         if (qglDrawBuffer)
5852                         {
5853                                 int status;
5854                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5855                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5856                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5857                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5858                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5859                         }
5860                 }
5861                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5862                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5863                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5864                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5865                 r_bloomstate.viewfbo = r_viewfbo.integer;
5866                 r_bloomstate.texturetype = textype;
5867         }
5868
5869         // when doing a reduced render (HDR) we want to use a smaller area
5870         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5871         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5872         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5873         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5874         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5875
5876         // set up a texcoord array for the full resolution screen image
5877         // (we have to keep this around to copy back during final render)
5878         r_bloomstate.screentexcoord2f[0] = 0;
5879         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5880         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5881         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5882         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5883         r_bloomstate.screentexcoord2f[5] = 0;
5884         r_bloomstate.screentexcoord2f[6] = 0;
5885         r_bloomstate.screentexcoord2f[7] = 0;
5886
5887         // set up a texcoord array for the reduced resolution bloom image
5888         // (which will be additive blended over the screen image)
5889         r_bloomstate.bloomtexcoord2f[0] = 0;
5890         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5892         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5893         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5894         r_bloomstate.bloomtexcoord2f[5] = 0;
5895         r_bloomstate.bloomtexcoord2f[6] = 0;
5896         r_bloomstate.bloomtexcoord2f[7] = 0;
5897
5898         switch(vid.renderpath)
5899         {
5900         case RENDERPATH_GL11:
5901         case RENDERPATH_GL13:
5902         case RENDERPATH_GL20:
5903         case RENDERPATH_SOFT:
5904         case RENDERPATH_GLES1:
5905         case RENDERPATH_GLES2:
5906                 break;
5907         case RENDERPATH_D3D9:
5908         case RENDERPATH_D3D10:
5909         case RENDERPATH_D3D11:
5910                 {
5911                         int i;
5912                         for (i = 0;i < 4;i++)
5913                         {
5914                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5915                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5916                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5917                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5918                         }
5919                 }
5920                 break;
5921         }
5922
5923         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5924         {
5925                 r_bloomstate.enabled = true;
5926                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5927         }
5928
5929         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5930
5931         if (r_bloomstate.fbo_framebuffer)
5932                 r_refdef.view.clear = true;
5933 }
5934
5935 void R_Bloom_CopyBloomTexture(float colorscale)
5936 {
5937         r_refdef.stats.bloom++;
5938
5939         // scale down screen texture to the bloom texture size
5940         CHECKGLERROR
5941         R_Mesh_SetMainRenderTargets();
5942         R_SetViewport(&r_bloomstate.viewport);
5943         GL_BlendFunc(GL_ONE, GL_ZERO);
5944         GL_Color(colorscale, colorscale, colorscale, 1);
5945         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
5946         switch(vid.renderpath)
5947         {
5948         case RENDERPATH_GL11:
5949         case RENDERPATH_GL13:
5950         case RENDERPATH_GL20:
5951         case RENDERPATH_GLES1:
5952         case RENDERPATH_GLES2:
5953         case RENDERPATH_SOFT:
5954                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5955                 break;
5956         case RENDERPATH_D3D9:
5957         case RENDERPATH_D3D10:
5958         case RENDERPATH_D3D11:
5959                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5960                 break;
5961         }
5962         // TODO: do boxfilter scale-down in shader?
5963         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5964         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5966
5967         // we now have a bloom image in the framebuffer
5968         // copy it into the bloom image texture for later processing
5969         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5970         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5971 }
5972
5973 void R_Bloom_CopyHDRTexture(void)
5974 {
5975         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5976         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5977 }
5978
5979 void R_Bloom_MakeTexture(void)
5980 {
5981         int x, range, dir;
5982         float xoffset, yoffset, r, brighten;
5983
5984         r_refdef.stats.bloom++;
5985
5986         R_ResetViewRendering2D();
5987
5988         // we have a bloom image in the framebuffer
5989         CHECKGLERROR
5990         R_SetViewport(&r_bloomstate.viewport);
5991
5992         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5993         {
5994                 x *= 2;
5995                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5996                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5997                 GL_Color(r,r,r,1);
5998                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5999                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6000                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6002
6003                 // copy the vertically blurred bloom view to a texture
6004                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6005                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6006         }
6007
6008         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6009         brighten = r_bloom_brighten.value;
6010         if (r_bloomstate.hdr)
6011                 brighten *= r_hdr_range.value;
6012         brighten = sqrt(brighten);
6013         if(range >= 1)
6014                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6015         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6016
6017         for (dir = 0;dir < 2;dir++)
6018         {
6019                 // blend on at multiple vertical offsets to achieve a vertical blur
6020                 // TODO: do offset blends using GLSL
6021                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6022                 GL_BlendFunc(GL_ONE, GL_ZERO);
6023                 for (x = -range;x <= range;x++)
6024                 {
6025                         if (!dir){xoffset = 0;yoffset = x;}
6026                         else {xoffset = x;yoffset = 0;}
6027                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6028                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6029                         // compute a texcoord array with the specified x and y offset
6030                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6031                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6034                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6035                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6036                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6037                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6038                         // this r value looks like a 'dot' particle, fading sharply to
6039                         // black at the edges
6040                         // (probably not realistic but looks good enough)
6041                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6042                         //r = brighten/(range*2+1);
6043                         r = brighten / (range * 2 + 1);
6044                         if(range >= 1)
6045                                 r *= (1 - x*x/(float)(range*range));
6046                         GL_Color(r, r, r, 1);
6047                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6048                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6049                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6050                         GL_BlendFunc(GL_ONE, GL_ONE);
6051                 }
6052
6053                 // copy the vertically blurred bloom view to a texture
6054                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6055                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6056         }
6057 }
6058
6059 void R_HDR_RenderBloomTexture(void)
6060 {
6061         int oldwidth, oldheight;
6062         float oldcolorscale;
6063         qboolean oldwaterstate;
6064
6065         oldwaterstate = r_waterstate.enabled;
6066         oldcolorscale = r_refdef.view.colorscale;
6067         oldwidth = r_refdef.view.width;
6068         oldheight = r_refdef.view.height;
6069         r_refdef.view.width = r_bloomstate.bloomwidth;
6070         r_refdef.view.height = r_bloomstate.bloomheight;
6071
6072         if(r_hdr.integer < 2)
6073                 r_waterstate.enabled = false;
6074
6075         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6076         // TODO: add exposure compensation features
6077         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6078
6079         r_refdef.view.showdebug = false;
6080         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6081
6082         R_ResetViewRendering3D();
6083
6084         R_ClearScreen(r_refdef.fogenabled);
6085         if (r_timereport_active)
6086                 R_TimeReport("HDRclear");
6087
6088         R_View_Update();
6089         if (r_timereport_active)
6090                 R_TimeReport("visibility");
6091
6092         // only do secondary renders with HDR if r_hdr is 2 or higher
6093         r_waterstate.numwaterplanes = 0;
6094         if (r_waterstate.enabled)
6095                 R_RenderWaterPlanes();
6096
6097         r_refdef.view.showdebug = true;
6098         R_RenderScene();
6099         r_waterstate.numwaterplanes = 0;
6100
6101         R_ResetViewRendering2D();
6102
6103         R_Bloom_CopyHDRTexture();
6104         R_Bloom_MakeTexture();
6105
6106         // restore the view settings
6107         r_waterstate.enabled = oldwaterstate;
6108         r_refdef.view.width = oldwidth;
6109         r_refdef.view.height = oldheight;
6110         r_refdef.view.colorscale = oldcolorscale;
6111
6112         R_ResetViewRendering3D();
6113
6114         R_ClearScreen(r_refdef.fogenabled);
6115         if (r_timereport_active)
6116                 R_TimeReport("viewclear");
6117 }
6118
6119 static void R_BlendView(void)
6120 {
6121         unsigned int permutation;
6122         float uservecs[4][4];
6123
6124         switch (vid.renderpath)
6125         {
6126         case RENDERPATH_GL20:
6127         case RENDERPATH_D3D9:
6128         case RENDERPATH_D3D10:
6129         case RENDERPATH_D3D11:
6130         case RENDERPATH_SOFT:
6131         case RENDERPATH_GLES2:
6132                 permutation =
6133                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6134                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6135                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6136                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6137                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6138
6139                 if (r_bloomstate.texture_screen)
6140                 {
6141                         // make sure the buffer is available
6142                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6143
6144                         R_ResetViewRendering2D();
6145                         R_Mesh_SetMainRenderTargets();
6146
6147                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6148                         {
6149                                 // declare variables
6150                                 float speed;
6151                                 static float avgspeed;
6152
6153                                 speed = VectorLength(cl.movement_velocity);
6154
6155                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6156                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6157
6158                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6159                                 speed = bound(0, speed, 1);
6160                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6161
6162                                 // calculate values into a standard alpha
6163                                 cl.motionbluralpha = 1 - exp(-
6164                                                 (
6165                                                  (r_motionblur.value * speed / 80)
6166                                                  +
6167                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6168                                                 )
6169                                                 /
6170                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6171                                            );
6172
6173                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6174                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6175                                 // apply the blur
6176                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6177                                 {
6178                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6179                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6180                                         switch(vid.renderpath)
6181                                         {
6182                                         case RENDERPATH_GL11:
6183                                         case RENDERPATH_GL13:
6184                                         case RENDERPATH_GL20:
6185                                         case RENDERPATH_GLES1:
6186                                         case RENDERPATH_GLES2:
6187                                         case RENDERPATH_SOFT:
6188                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6189                                                 break;
6190                                         case RENDERPATH_D3D9:
6191                                         case RENDERPATH_D3D10:
6192                                         case RENDERPATH_D3D11:
6193                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6194                                                 break;
6195                                         }
6196                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6197                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6198                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6199                                 }
6200                         }
6201
6202                         // copy view into the screen texture
6203                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6204                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6205                 }
6206                 else if (!r_bloomstate.texture_bloom)
6207                 {
6208                         // we may still have to do view tint...
6209                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6210                         {
6211                                 // apply a color tint to the whole view
6212                                 R_ResetViewRendering2D();
6213                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6215                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6216                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6217                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6218                         }
6219                         break; // no screen processing, no bloom, skip it
6220                 }
6221
6222                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6223                 {
6224                         // render simple bloom effect
6225                         // copy the screen and shrink it and darken it for the bloom process
6226                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6227                         // make the bloom texture
6228                         R_Bloom_MakeTexture();
6229                 }
6230
6231 #if _MSC_VER >= 1400
6232 #define sscanf sscanf_s
6233 #endif
6234                 memset(uservecs, 0, sizeof(uservecs));
6235                 if (r_glsl_postprocess_uservec1_enable.integer)
6236                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6237                 if (r_glsl_postprocess_uservec2_enable.integer)
6238                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6239                 if (r_glsl_postprocess_uservec3_enable.integer)
6240                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6241                 if (r_glsl_postprocess_uservec4_enable.integer)
6242                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6243
6244                 R_ResetViewRendering2D();
6245                 GL_Color(1, 1, 1, 1);
6246                 GL_BlendFunc(GL_ONE, GL_ZERO);
6247
6248                 switch(vid.renderpath)
6249                 {
6250                 case RENDERPATH_GL20:
6251                 case RENDERPATH_GLES2:
6252                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6254                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6255                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6256                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6257                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6258                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6260                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6261                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6262                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6263                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6264                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6266                         break;
6267                 case RENDERPATH_D3D9:
6268 #ifdef SUPPORTD3D
6269                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6270                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6271                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6272                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6273                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6274                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6275                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6276                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6277                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6278                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6279                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6280                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6281                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6282                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6283                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6284 #endif
6285                         break;
6286                 case RENDERPATH_D3D10:
6287                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6288                         break;
6289                 case RENDERPATH_D3D11:
6290                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6291                         break;
6292                 case RENDERPATH_SOFT:
6293                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6294                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6295                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6296                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6297                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6298                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6299                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6300                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6301                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6302                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6303                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6304                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6305                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6306                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6307                         break;
6308                 default:
6309                         break;
6310                 }
6311                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6312                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6313                 break;
6314         case RENDERPATH_GL11:
6315         case RENDERPATH_GL13:
6316         case RENDERPATH_GLES1:
6317                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6318                 {
6319                         // apply a color tint to the whole view
6320                         R_ResetViewRendering2D();
6321                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6322                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6323                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6324                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6326                 }
6327                 break;
6328         }
6329 }
6330
6331 matrix4x4_t r_waterscrollmatrix;
6332
6333 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6334 {
6335         if (r_refdef.fog_density)
6336         {
6337                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6338                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6339                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6340
6341                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6342                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6343                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6344                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6345
6346                 {
6347                         vec3_t fogvec;
6348                         VectorCopy(r_refdef.fogcolor, fogvec);
6349                         //   color.rgb *= ContrastBoost * SceneBrightness;
6350                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6351                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6352                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6353                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6354                 }
6355         }
6356 }
6357
6358 void R_UpdateVariables(void)
6359 {
6360         R_Textures_Frame();
6361
6362         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6363
6364         r_refdef.farclip = r_farclip_base.value;
6365         if (r_refdef.scene.worldmodel)
6366                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6367         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6368
6369         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6370                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6371         r_refdef.polygonfactor = 0;
6372         r_refdef.polygonoffset = 0;
6373         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6374         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6375
6376         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6377         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6378         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6379         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6380         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6381         if (FAKELIGHT_ENABLED)
6382         {
6383                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6384         }
6385         if (r_showsurfaces.integer)
6386         {
6387                 r_refdef.scene.rtworld = false;
6388                 r_refdef.scene.rtworldshadows = false;
6389                 r_refdef.scene.rtdlight = false;
6390                 r_refdef.scene.rtdlightshadows = false;
6391                 r_refdef.lightmapintensity = 0;
6392         }
6393
6394         if (gamemode == GAME_NEHAHRA)
6395         {
6396                 if (gl_fogenable.integer)
6397                 {
6398                         r_refdef.oldgl_fogenable = true;
6399                         r_refdef.fog_density = gl_fogdensity.value;
6400                         r_refdef.fog_red = gl_fogred.value;
6401                         r_refdef.fog_green = gl_foggreen.value;
6402                         r_refdef.fog_blue = gl_fogblue.value;
6403                         r_refdef.fog_alpha = 1;
6404                         r_refdef.fog_start = 0;
6405                         r_refdef.fog_end = gl_skyclip.value;
6406                         r_refdef.fog_height = 1<<30;
6407                         r_refdef.fog_fadedepth = 128;
6408                 }
6409                 else if (r_refdef.oldgl_fogenable)
6410                 {
6411                         r_refdef.oldgl_fogenable = false;
6412                         r_refdef.fog_density = 0;
6413                         r_refdef.fog_red = 0;
6414                         r_refdef.fog_green = 0;
6415                         r_refdef.fog_blue = 0;
6416                         r_refdef.fog_alpha = 0;
6417                         r_refdef.fog_start = 0;
6418                         r_refdef.fog_end = 0;
6419                         r_refdef.fog_height = 1<<30;
6420                         r_refdef.fog_fadedepth = 128;
6421                 }
6422         }
6423
6424         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6425         r_refdef.fog_start = max(0, r_refdef.fog_start);
6426         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6427
6428         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6429
6430         if (r_refdef.fog_density && r_drawfog.integer)
6431         {
6432                 r_refdef.fogenabled = true;
6433                 // this is the point where the fog reaches 0.9986 alpha, which we
6434                 // consider a good enough cutoff point for the texture
6435                 // (0.9986 * 256 == 255.6)
6436                 if (r_fog_exp2.integer)
6437                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6438                 else
6439                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6440                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6441                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6442                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6443                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6444                         R_BuildFogHeightTexture();
6445                 // fog color was already set
6446                 // update the fog texture
6447                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6448                         R_BuildFogTexture();
6449                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6450                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6451         }
6452         else
6453                 r_refdef.fogenabled = false;
6454
6455         switch(vid.renderpath)
6456         {
6457         case RENDERPATH_GL20:
6458         case RENDERPATH_D3D9:
6459         case RENDERPATH_D3D10:
6460         case RENDERPATH_D3D11:
6461         case RENDERPATH_SOFT:
6462         case RENDERPATH_GLES2:
6463                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6464                 {
6465                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6466                         {
6467                                 // build GLSL gamma texture
6468 #define RAMPWIDTH 256
6469                                 unsigned short ramp[RAMPWIDTH * 3];
6470                                 unsigned char rampbgr[RAMPWIDTH][4];
6471                                 int i;
6472
6473                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6474
6475                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6476                                 for(i = 0; i < RAMPWIDTH; ++i)
6477                                 {
6478                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6479                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6480                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6481                                         rampbgr[i][3] = 0;
6482                                 }
6483                                 if (r_texture_gammaramps)
6484                                 {
6485                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6486                                 }
6487                                 else
6488                                 {
6489                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6490                                 }
6491                         }
6492                 }
6493                 else
6494                 {
6495                         // remove GLSL gamma texture
6496                 }
6497                 break;
6498         case RENDERPATH_GL11:
6499         case RENDERPATH_GL13:
6500         case RENDERPATH_GLES1:
6501                 break;
6502         }
6503 }
6504
6505 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6506 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6507 /*
6508 ================
6509 R_SelectScene
6510 ================
6511 */
6512 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6513         if( scenetype != r_currentscenetype ) {
6514                 // store the old scenetype
6515                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6516                 r_currentscenetype = scenetype;
6517                 // move in the new scene
6518                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6519         }
6520 }
6521
6522 /*
6523 ================
6524 R_GetScenePointer
6525 ================
6526 */
6527 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6528 {
6529         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6530         if( scenetype == r_currentscenetype ) {
6531                 return &r_refdef.scene;
6532         } else {
6533                 return &r_scenes_store[ scenetype ];
6534         }
6535 }
6536
6537 /*
6538 ================
6539 R_RenderView
6540 ================
6541 */
6542 int dpsoftrast_test;
6543 void R_RenderView(void)
6544 {
6545         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6546
6547         dpsoftrast_test = r_test.integer;
6548
6549         if (r_timereport_active)
6550                 R_TimeReport("start");
6551         r_textureframe++; // used only by R_GetCurrentTexture
6552         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6553
6554         if(R_CompileShader_CheckStaticParms())
6555                 R_GLSL_Restart_f();
6556
6557         if (!r_drawentities.integer)
6558                 r_refdef.scene.numentities = 0;
6559
6560         R_AnimCache_ClearCache();
6561         R_FrameData_NewFrame();
6562
6563         /* adjust for stereo display */
6564         if(R_Stereo_Active())
6565         {
6566                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6567                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6568         }
6569
6570         if (r_refdef.view.isoverlay)
6571         {
6572                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6573                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6574                 R_TimeReport("depthclear");
6575
6576                 r_refdef.view.showdebug = false;
6577
6578                 r_waterstate.enabled = false;
6579                 r_waterstate.numwaterplanes = 0;
6580
6581                 R_RenderScene();
6582
6583                 r_refdef.view.matrix = originalmatrix;
6584
6585                 CHECKGLERROR
6586                 return;
6587         }
6588
6589         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6590         {
6591                 r_refdef.view.matrix = originalmatrix;
6592                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6593         }
6594
6595         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6596
6597         R_RenderView_UpdateViewVectors();
6598
6599         R_Shadow_UpdateWorldLightSelection();
6600
6601         R_Bloom_StartFrame();
6602         R_Water_StartFrame();
6603
6604         CHECKGLERROR
6605         if (r_timereport_active)
6606                 R_TimeReport("viewsetup");
6607
6608         R_ResetViewRendering3D();
6609
6610         if (r_refdef.view.clear || r_refdef.fogenabled)
6611         {
6612                 R_ClearScreen(r_refdef.fogenabled);
6613                 if (r_timereport_active)
6614                         R_TimeReport("viewclear");
6615         }
6616         r_refdef.view.clear = true;
6617
6618         // this produces a bloom texture to be used in R_BlendView() later
6619         if (r_bloomstate.hdr)
6620         {
6621                 R_HDR_RenderBloomTexture();
6622                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6623                 r_textureframe++; // used only by R_GetCurrentTexture
6624         }
6625
6626         r_refdef.view.showdebug = true;
6627
6628         R_View_Update();
6629         if (r_timereport_active)
6630                 R_TimeReport("visibility");
6631
6632         r_waterstate.numwaterplanes = 0;
6633         if (r_waterstate.enabled)
6634                 R_RenderWaterPlanes();
6635
6636         R_RenderScene();
6637         r_waterstate.numwaterplanes = 0;
6638
6639         R_BlendView();
6640         if (r_timereport_active)
6641                 R_TimeReport("blendview");
6642
6643         GL_Scissor(0, 0, vid.width, vid.height);
6644         GL_ScissorTest(false);
6645
6646         r_refdef.view.matrix = originalmatrix;
6647
6648         CHECKGLERROR
6649 }
6650
6651 void R_RenderWaterPlanes(void)
6652 {
6653         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6654         {
6655                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6656                 if (r_timereport_active)
6657                         R_TimeReport("waterworld");
6658         }
6659
6660         // don't let sound skip if going slow
6661         if (r_refdef.scene.extraupdate)
6662                 S_ExtraUpdate ();
6663
6664         R_DrawModelsAddWaterPlanes();
6665         if (r_timereport_active)
6666                 R_TimeReport("watermodels");
6667
6668         if (r_waterstate.numwaterplanes)
6669         {
6670                 R_Water_ProcessPlanes();
6671                 if (r_timereport_active)
6672                         R_TimeReport("waterscenes");
6673         }
6674 }
6675
6676 extern void R_DrawLightningBeams (void);
6677 extern void VM_CL_AddPolygonsToMeshQueue (void);
6678 extern void R_DrawPortals (void);
6679 extern cvar_t cl_locs_show;
6680 static void R_DrawLocs(void);
6681 static void R_DrawEntityBBoxes(void);
6682 static void R_DrawModelDecals(void);
6683 extern void R_DrawModelShadows(void);
6684 extern void R_DrawModelShadowMaps(void);
6685 extern cvar_t cl_decals_newsystem;
6686 extern qboolean r_shadow_usingdeferredprepass;
6687 void R_RenderScene(void)
6688 {
6689         qboolean shadowmapping = false;
6690
6691         if (r_timereport_active)
6692                 R_TimeReport("beginscene");
6693
6694         r_refdef.stats.renders++;
6695
6696         R_UpdateFogColor();
6697
6698         // don't let sound skip if going slow
6699         if (r_refdef.scene.extraupdate)
6700                 S_ExtraUpdate ();
6701
6702         R_MeshQueue_BeginScene();
6703
6704         R_SkyStartFrame();
6705
6706         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
6707
6708         if (r_timereport_active)
6709                 R_TimeReport("skystartframe");
6710
6711         if (cl.csqc_vidvars.drawworld)
6712         {
6713                 // don't let sound skip if going slow
6714                 if (r_refdef.scene.extraupdate)
6715                         S_ExtraUpdate ();
6716
6717                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6718                 {
6719                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6720                         if (r_timereport_active)
6721                                 R_TimeReport("worldsky");
6722                 }
6723
6724                 if (R_DrawBrushModelsSky() && r_timereport_active)
6725                         R_TimeReport("bmodelsky");
6726
6727                 if (skyrendermasked && skyrenderlater)
6728                 {
6729                         // we have to force off the water clipping plane while rendering sky
6730                         R_SetupView(false);
6731                         R_Sky();
6732                         R_SetupView(true);
6733                         if (r_timereport_active)
6734                                 R_TimeReport("sky");
6735                 }
6736         }
6737
6738         R_AnimCache_CacheVisibleEntities();
6739         if (r_timereport_active)
6740                 R_TimeReport("animation");
6741
6742         R_Shadow_PrepareLights();
6743         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6744                 R_Shadow_PrepareModelShadows();
6745         if (r_timereport_active)
6746                 R_TimeReport("preparelights");
6747
6748         if (R_Shadow_ShadowMappingEnabled())
6749                 shadowmapping = true;
6750
6751         if (r_shadow_usingdeferredprepass)
6752                 R_Shadow_DrawPrepass();
6753
6754         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6755         {
6756                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6757                 if (r_timereport_active)
6758                         R_TimeReport("worlddepth");
6759         }
6760         if (r_depthfirst.integer >= 2)
6761         {
6762                 R_DrawModelsDepth();
6763                 if (r_timereport_active)
6764                         R_TimeReport("modeldepth");
6765         }
6766
6767         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6768         {
6769                 R_DrawModelShadowMaps();
6770                 R_ResetViewRendering3D();
6771                 // don't let sound skip if going slow
6772                 if (r_refdef.scene.extraupdate)
6773                         S_ExtraUpdate ();
6774         }
6775
6776         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6777         {
6778                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6779                 if (r_timereport_active)
6780                         R_TimeReport("world");
6781         }
6782
6783         // don't let sound skip if going slow
6784         if (r_refdef.scene.extraupdate)
6785                 S_ExtraUpdate ();
6786
6787         R_DrawModels();
6788         if (r_timereport_active)
6789                 R_TimeReport("models");
6790
6791         // don't let sound skip if going slow
6792         if (r_refdef.scene.extraupdate)
6793                 S_ExtraUpdate ();
6794
6795         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6796         {
6797                 R_DrawModelShadows();
6798                 R_ResetViewRendering3D();
6799                 // don't let sound skip if going slow
6800                 if (r_refdef.scene.extraupdate)
6801                         S_ExtraUpdate ();
6802         }
6803
6804         if (!r_shadow_usingdeferredprepass)
6805         {
6806                 R_Shadow_DrawLights();
6807                 if (r_timereport_active)
6808                         R_TimeReport("rtlights");
6809         }
6810
6811         // don't let sound skip if going slow
6812         if (r_refdef.scene.extraupdate)
6813                 S_ExtraUpdate ();
6814
6815         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6816         {
6817                 R_DrawModelShadows();
6818                 R_ResetViewRendering3D();
6819                 // don't let sound skip if going slow
6820                 if (r_refdef.scene.extraupdate)
6821                         S_ExtraUpdate ();
6822         }
6823
6824         if (cl.csqc_vidvars.drawworld)
6825         {
6826                 if (cl_decals_newsystem.integer)
6827                 {
6828                         R_DrawModelDecals();
6829                         if (r_timereport_active)
6830                                 R_TimeReport("modeldecals");
6831                 }
6832                 else
6833                 {
6834                         R_DrawDecals();
6835                         if (r_timereport_active)
6836                                 R_TimeReport("decals");
6837                 }
6838
6839                 R_DrawParticles();
6840                 if (r_timereport_active)
6841                         R_TimeReport("particles");
6842
6843                 R_DrawExplosions();
6844                 if (r_timereport_active)
6845                         R_TimeReport("explosions");
6846
6847                 R_DrawLightningBeams();
6848                 if (r_timereport_active)
6849                         R_TimeReport("lightning");
6850         }
6851
6852         VM_CL_AddPolygonsToMeshQueue();
6853
6854         if (r_refdef.view.showdebug)
6855         {
6856                 if (cl_locs_show.integer)
6857                 {
6858                         R_DrawLocs();
6859                         if (r_timereport_active)
6860                                 R_TimeReport("showlocs");
6861                 }
6862
6863                 if (r_drawportals.integer)
6864                 {
6865                         R_DrawPortals();
6866                         if (r_timereport_active)
6867                                 R_TimeReport("portals");
6868                 }
6869
6870                 if (r_showbboxes.value > 0)
6871                 {
6872                         R_DrawEntityBBoxes();
6873                         if (r_timereport_active)
6874                                 R_TimeReport("bboxes");
6875                 }
6876         }
6877
6878         if (r_transparent.integer)
6879         {
6880                 R_MeshQueue_RenderTransparent();
6881                 if (r_timereport_active)
6882                         R_TimeReport("drawtrans");
6883         }
6884
6885         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
6886         {
6887                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6888                 if (r_timereport_active)
6889                         R_TimeReport("worlddebug");
6890                 R_DrawModelsDebug();
6891                 if (r_timereport_active)
6892                         R_TimeReport("modeldebug");
6893         }
6894
6895         if (cl.csqc_vidvars.drawworld)
6896         {
6897                 R_Shadow_DrawCoronas();
6898                 if (r_timereport_active)
6899                         R_TimeReport("coronas");
6900         }
6901
6902 #if 0
6903         {
6904                 GL_DepthTest(false);
6905                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6906                 GL_Color(1, 1, 1, 1);
6907                 qglBegin(GL_POLYGON);
6908                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6909                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6910                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6911                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6912                 qglEnd();
6913                 qglBegin(GL_POLYGON);
6914                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
6915                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
6916                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
6917                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
6918                 qglEnd();
6919                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6920         }
6921 #endif
6922
6923         // don't let sound skip if going slow
6924         if (r_refdef.scene.extraupdate)
6925                 S_ExtraUpdate ();
6926
6927         R_ResetViewRendering2D();
6928 }
6929
6930 static const unsigned short bboxelements[36] =
6931 {
6932         5, 1, 3, 5, 3, 7,
6933         6, 2, 0, 6, 0, 4,
6934         7, 3, 2, 7, 2, 6,
6935         4, 0, 1, 4, 1, 5,
6936         4, 5, 7, 4, 7, 6,
6937         1, 0, 2, 1, 2, 3,
6938 };
6939
6940 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6941 {
6942         int i;
6943         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6944
6945         RSurf_ActiveWorldEntity();
6946
6947         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948         GL_DepthMask(false);
6949         GL_DepthRange(0, 1);
6950         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6951 //      R_Mesh_ResetTextureState();
6952
6953         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6954         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6955         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6956         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6957         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6958         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6959         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6960         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6961         R_FillColors(color4f, 8, cr, cg, cb, ca);
6962         if (r_refdef.fogenabled)
6963         {
6964                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6965                 {
6966                         f1 = RSurf_FogVertex(v);
6967                         f2 = 1 - f1;
6968                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6969                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6970                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6971                 }
6972         }
6973         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6974         R_Mesh_ResetTextureState();
6975         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6976         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6977 }
6978
6979 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6980 {
6981         int i;
6982         float color[4];
6983         prvm_edict_t *edict;
6984         prvm_prog_t *prog_save = prog;
6985
6986         // this function draws bounding boxes of server entities
6987         if (!sv.active)
6988                 return;
6989
6990         GL_CullFace(GL_NONE);
6991         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6992
6993         prog = 0;
6994         SV_VM_Begin();
6995         for (i = 0;i < numsurfaces;i++)
6996         {
6997                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6998                 switch ((int)edict->fields.server->solid)
6999                 {
7000                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7001                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7002                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7003                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7004                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7005                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7006                 }
7007                 color[3] *= r_showbboxes.value;
7008                 color[3] = bound(0, color[3], 1);
7009                 GL_DepthTest(!r_showdisabledepthtest.integer);
7010                 GL_CullFace(r_refdef.view.cullface_front);
7011                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7012         }
7013         SV_VM_End();
7014         prog = prog_save;
7015 }
7016
7017 static void R_DrawEntityBBoxes(void)
7018 {
7019         int i;
7020         prvm_edict_t *edict;
7021         vec3_t center;
7022         prvm_prog_t *prog_save = prog;
7023
7024         // this function draws bounding boxes of server entities
7025         if (!sv.active)
7026                 return;
7027
7028         prog = 0;
7029         SV_VM_Begin();
7030         for (i = 0;i < prog->num_edicts;i++)
7031         {
7032                 edict = PRVM_EDICT_NUM(i);
7033                 if (edict->priv.server->free)
7034                         continue;
7035                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7036                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7037                         continue;
7038                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7039                         continue;
7040                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7041                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7042         }
7043         SV_VM_End();
7044         prog = prog_save;
7045 }
7046
7047 static const int nomodelelement3i[24] =
7048 {
7049         5, 2, 0,
7050         5, 1, 2,
7051         5, 0, 3,
7052         5, 3, 1,
7053         0, 2, 4,
7054         2, 1, 4,
7055         3, 0, 4,
7056         1, 3, 4
7057 };
7058
7059 static const unsigned short nomodelelement3s[24] =
7060 {
7061         5, 2, 0,
7062         5, 1, 2,
7063         5, 0, 3,
7064         5, 3, 1,
7065         0, 2, 4,
7066         2, 1, 4,
7067         3, 0, 4,
7068         1, 3, 4
7069 };
7070
7071 static const float nomodelvertex3f[6*3] =
7072 {
7073         -16,   0,   0,
7074          16,   0,   0,
7075           0, -16,   0,
7076           0,  16,   0,
7077           0,   0, -16,
7078           0,   0,  16
7079 };
7080
7081 static const float nomodelcolor4f[6*4] =
7082 {
7083         0.0f, 0.0f, 0.5f, 1.0f,
7084         0.0f, 0.0f, 0.5f, 1.0f,
7085         0.0f, 0.5f, 0.0f, 1.0f,
7086         0.0f, 0.5f, 0.0f, 1.0f,
7087         0.5f, 0.0f, 0.0f, 1.0f,
7088         0.5f, 0.0f, 0.0f, 1.0f
7089 };
7090
7091 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7092 {
7093         int i;
7094         float f1, f2, *c;
7095         float color4f[6*4];
7096
7097         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7098
7099         // this is only called once per entity so numsurfaces is always 1, and
7100         // surfacelist is always {0}, so this code does not handle batches
7101
7102         if (rsurface.ent_flags & RENDER_ADDITIVE)
7103         {
7104                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7105                 GL_DepthMask(false);
7106         }
7107         else if (rsurface.colormod[3] < 1)
7108         {
7109                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7110                 GL_DepthMask(false);
7111         }
7112         else
7113         {
7114                 GL_BlendFunc(GL_ONE, GL_ZERO);
7115                 GL_DepthMask(true);
7116         }
7117         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7118         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7119         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7120         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7121         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7122         for (i = 0, c = color4f;i < 6;i++, c += 4)
7123         {
7124                 c[0] *= rsurface.colormod[0];
7125                 c[1] *= rsurface.colormod[1];
7126                 c[2] *= rsurface.colormod[2];
7127                 c[3] *= rsurface.colormod[3];
7128         }
7129         if (r_refdef.fogenabled)
7130         {
7131                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7132                 {
7133                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7134                         f2 = 1 - f1;
7135                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7136                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7137                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7138                 }
7139         }
7140 //      R_Mesh_ResetTextureState();
7141         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7142         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7143         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7144 }
7145
7146 void R_DrawNoModel(entity_render_t *ent)
7147 {
7148         vec3_t org;
7149         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7150         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7151                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7152         else
7153                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7154 }
7155
7156 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7157 {
7158         vec3_t right1, right2, diff, normal;
7159
7160         VectorSubtract (org2, org1, normal);
7161
7162         // calculate 'right' vector for start
7163         VectorSubtract (r_refdef.view.origin, org1, diff);
7164         CrossProduct (normal, diff, right1);
7165         VectorNormalize (right1);
7166
7167         // calculate 'right' vector for end
7168         VectorSubtract (r_refdef.view.origin, org2, diff);
7169         CrossProduct (normal, diff, right2);
7170         VectorNormalize (right2);
7171
7172         vert[ 0] = org1[0] + width * right1[0];
7173         vert[ 1] = org1[1] + width * right1[1];
7174         vert[ 2] = org1[2] + width * right1[2];
7175         vert[ 3] = org1[0] - width * right1[0];
7176         vert[ 4] = org1[1] - width * right1[1];
7177         vert[ 5] = org1[2] - width * right1[2];
7178         vert[ 6] = org2[0] - width * right2[0];
7179         vert[ 7] = org2[1] - width * right2[1];
7180         vert[ 8] = org2[2] - width * right2[2];
7181         vert[ 9] = org2[0] + width * right2[0];
7182         vert[10] = org2[1] + width * right2[1];
7183         vert[11] = org2[2] + width * right2[2];
7184 }
7185
7186 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7187 {
7188         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7189         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7190         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7191         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7192         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7193         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7194         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7195         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7196         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7197         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7198         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7199         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7200 }
7201
7202 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7203 {
7204         int i;
7205         float *vertex3f;
7206         float v[3];
7207         VectorSet(v, x, y, z);
7208         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7209                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7210                         break;
7211         if (i == mesh->numvertices)
7212         {
7213                 if (mesh->numvertices < mesh->maxvertices)
7214                 {
7215                         VectorCopy(v, vertex3f);
7216                         mesh->numvertices++;
7217                 }
7218                 return mesh->numvertices;
7219         }
7220         else
7221                 return i;
7222 }
7223
7224 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7225 {
7226         int i;
7227         int *e, element[3];
7228         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7229         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7230         e = mesh->element3i + mesh->numtriangles * 3;
7231         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7232         {
7233                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7234                 if (mesh->numtriangles < mesh->maxtriangles)
7235                 {
7236                         *e++ = element[0];
7237                         *e++ = element[1];
7238                         *e++ = element[2];
7239                         mesh->numtriangles++;
7240                 }
7241                 element[1] = element[2];
7242         }
7243 }
7244
7245 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7246 {
7247         int i;
7248         int *e, element[3];
7249         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7250         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7251         e = mesh->element3i + mesh->numtriangles * 3;
7252         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7253         {
7254                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7255                 if (mesh->numtriangles < mesh->maxtriangles)
7256                 {
7257                         *e++ = element[0];
7258                         *e++ = element[1];
7259                         *e++ = element[2];
7260                         mesh->numtriangles++;
7261                 }
7262                 element[1] = element[2];
7263         }
7264 }
7265
7266 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7267 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7268 {
7269         int planenum, planenum2;
7270         int w;
7271         int tempnumpoints;
7272         mplane_t *plane, *plane2;
7273         double maxdist;
7274         double temppoints[2][256*3];
7275         // figure out how large a bounding box we need to properly compute this brush
7276         maxdist = 0;
7277         for (w = 0;w < numplanes;w++)
7278                 maxdist = max(maxdist, fabs(planes[w].dist));
7279         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7280         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7281         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7282         {
7283                 w = 0;
7284                 tempnumpoints = 4;
7285                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7286                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7287                 {
7288                         if (planenum2 == planenum)
7289                                 continue;
7290                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7291                         w = !w;
7292                 }
7293                 if (tempnumpoints < 3)
7294                         continue;
7295                 // generate elements forming a triangle fan for this polygon
7296                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7297         }
7298 }
7299
7300 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7301 {
7302         texturelayer_t *layer;
7303         layer = t->currentlayers + t->currentnumlayers++;
7304         layer->type = type;
7305         layer->depthmask = depthmask;
7306         layer->blendfunc1 = blendfunc1;
7307         layer->blendfunc2 = blendfunc2;
7308         layer->texture = texture;
7309         layer->texmatrix = *matrix;
7310         layer->color[0] = r;
7311         layer->color[1] = g;
7312         layer->color[2] = b;
7313         layer->color[3] = a;
7314 }
7315
7316 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7317 {
7318         if(parms[0] == 0 && parms[1] == 0)
7319                 return false;
7320         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7322                         return false;
7323         return true;
7324 }
7325
7326 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7327 {
7328         double index, f;
7329         index = parms[2] + r_refdef.scene.time * parms[3];
7330         index -= floor(index);
7331         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7332         {
7333         default:
7334         case Q3WAVEFUNC_NONE:
7335         case Q3WAVEFUNC_NOISE:
7336         case Q3WAVEFUNC_COUNT:
7337                 f = 0;
7338                 break;
7339         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7340         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7341         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7342         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7343         case Q3WAVEFUNC_TRIANGLE:
7344                 index *= 4;
7345                 f = index - floor(index);
7346                 if (index < 1)
7347                         f = f;
7348                 else if (index < 2)
7349                         f = 1 - f;
7350                 else if (index < 3)
7351                         f = -f;
7352                 else
7353                         f = -(1 - f);
7354                 break;
7355         }
7356         f = parms[0] + parms[1] * f;
7357         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7358                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7359         return (float) f;
7360 }
7361
7362 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7363 {
7364         int w, h, idx;
7365         float f;
7366         float tcmat[12];
7367         matrix4x4_t matrix, temp;
7368         switch(tcmod->tcmod)
7369         {
7370                 case Q3TCMOD_COUNT:
7371                 case Q3TCMOD_NONE:
7372                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7373                                 matrix = r_waterscrollmatrix;
7374                         else
7375                                 matrix = identitymatrix;
7376                         break;
7377                 case Q3TCMOD_ENTITYTRANSLATE:
7378                         // this is used in Q3 to allow the gamecode to control texcoord
7379                         // scrolling on the entity, which is not supported in darkplaces yet.
7380                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7381                         break;
7382                 case Q3TCMOD_ROTATE:
7383                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7384                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7385                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7386                         break;
7387                 case Q3TCMOD_SCALE:
7388                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7389                         break;
7390                 case Q3TCMOD_SCROLL:
7391                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7392                         break;
7393                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7394                         w = (int) tcmod->parms[0];
7395                         h = (int) tcmod->parms[1];
7396                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7397                         f = f - floor(f);
7398                         idx = (int) floor(f * w * h);
7399                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7400                         break;
7401                 case Q3TCMOD_STRETCH:
7402                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7403                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7404                         break;
7405                 case Q3TCMOD_TRANSFORM:
7406                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7407                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7408                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7409                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7410                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7411                         break;
7412                 case Q3TCMOD_TURBULENT:
7413                         // this is handled in the RSurf_PrepareVertices function
7414                         matrix = identitymatrix;
7415                         break;
7416         }
7417         temp = *texmatrix;
7418         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7419 }
7420
7421 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7422 {
7423         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7424         char name[MAX_QPATH];
7425         skinframe_t *skinframe;
7426         unsigned char pixels[296*194];
7427         strlcpy(cache->name, skinname, sizeof(cache->name));
7428         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7429         if (developer_loading.integer)
7430                 Con_Printf("loading %s\n", name);
7431         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7432         if (!skinframe || !skinframe->base)
7433         {
7434                 unsigned char *f;
7435                 fs_offset_t filesize;
7436                 skinframe = NULL;
7437                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7438                 if (f)
7439                 {
7440                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7441                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7442                         Mem_Free(f);
7443                 }
7444         }
7445         cache->skinframe = skinframe;
7446 }
7447
7448 texture_t *R_GetCurrentTexture(texture_t *t)
7449 {
7450         int i;
7451         const entity_render_t *ent = rsurface.entity;
7452         dp_model_t *model = ent->model;
7453         q3shaderinfo_layer_tcmod_t *tcmod;
7454
7455         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7456                 return t->currentframe;
7457         t->update_lastrenderframe = r_textureframe;
7458         t->update_lastrenderentity = (void *)ent;
7459
7460         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7461                 t->camera_entity = ent->entitynumber;
7462         else
7463                 t->camera_entity = 0;
7464
7465         // switch to an alternate material if this is a q1bsp animated material
7466         {
7467                 texture_t *texture = t;
7468                 int s = rsurface.ent_skinnum;
7469                 if ((unsigned int)s >= (unsigned int)model->numskins)
7470                         s = 0;
7471                 if (model->skinscenes)
7472                 {
7473                         if (model->skinscenes[s].framecount > 1)
7474                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7475                         else
7476                                 s = model->skinscenes[s].firstframe;
7477                 }
7478                 if (s > 0)
7479                         t = t + s * model->num_surfaces;
7480                 if (t->animated)
7481                 {
7482                         // use an alternate animation if the entity's frame is not 0,
7483                         // and only if the texture has an alternate animation
7484                         if (rsurface.ent_alttextures && t->anim_total[1])
7485                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7486                         else
7487                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7488                 }
7489                 texture->currentframe = t;
7490         }
7491
7492         // update currentskinframe to be a qw skin or animation frame
7493         if (rsurface.ent_qwskin >= 0)
7494         {
7495                 i = rsurface.ent_qwskin;
7496                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7497                 {
7498                         r_qwskincache_size = cl.maxclients;
7499                         if (r_qwskincache)
7500                                 Mem_Free(r_qwskincache);
7501                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7502                 }
7503                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7504                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7505                 t->currentskinframe = r_qwskincache[i].skinframe;
7506                 if (t->currentskinframe == NULL)
7507                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7508         }
7509         else if (t->numskinframes >= 2)
7510                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7511         if (t->backgroundnumskinframes >= 2)
7512                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7513
7514         t->currentmaterialflags = t->basematerialflags;
7515         t->currentalpha = rsurface.colormod[3];
7516         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7517                 t->currentalpha *= r_wateralpha.value;
7518         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7519                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7520         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7521                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7522         if (!(rsurface.ent_flags & RENDER_LIGHT))
7523                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7524         else if (FAKELIGHT_ENABLED)
7525         {
7526                 // no modellight if using fakelight for the map
7527         }
7528         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7529         {
7530                 // pick a model lighting mode
7531                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7532                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7533                 else
7534                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7535         }
7536         if (rsurface.ent_flags & RENDER_ADDITIVE)
7537                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538         else if (t->currentalpha < 1)
7539                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7540         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7541                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7542         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7543                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7544         if (t->backgroundnumskinframes)
7545                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7546         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7547         {
7548                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7549                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7550         }
7551         else
7552                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7553         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7554                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7555
7556         // there is no tcmod
7557         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7558         {
7559                 t->currenttexmatrix = r_waterscrollmatrix;
7560                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7561         }
7562         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7563         {
7564                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7565                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7566         }
7567
7568         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7570         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7571                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7572
7573         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7574         if (t->currentskinframe->qpixels)
7575                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7576         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7577         if (!t->basetexture)
7578                 t->basetexture = r_texture_notexture;
7579         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7580         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7581         t->nmaptexture = t->currentskinframe->nmap;
7582         if (!t->nmaptexture)
7583                 t->nmaptexture = r_texture_blanknormalmap;
7584         t->glosstexture = r_texture_black;
7585         t->glowtexture = t->currentskinframe->glow;
7586         t->fogtexture = t->currentskinframe->fog;
7587         t->reflectmasktexture = t->currentskinframe->reflect;
7588         if (t->backgroundnumskinframes)
7589         {
7590                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7591                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7592                 t->backgroundglosstexture = r_texture_black;
7593                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7594                 if (!t->backgroundnmaptexture)
7595                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7596         }
7597         else
7598         {
7599                 t->backgroundbasetexture = r_texture_white;
7600                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7601                 t->backgroundglosstexture = r_texture_black;
7602                 t->backgroundglowtexture = NULL;
7603         }
7604         t->specularpower = r_shadow_glossexponent.value;
7605         // TODO: store reference values for these in the texture?
7606         t->specularscale = 0;
7607         if (r_shadow_gloss.integer > 0)
7608         {
7609                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7610                 {
7611                         if (r_shadow_glossintensity.value > 0)
7612                         {
7613                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7614                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7615                                 t->specularscale = r_shadow_glossintensity.value;
7616                         }
7617                 }
7618                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7619                 {
7620                         t->glosstexture = r_texture_white;
7621                         t->backgroundglosstexture = r_texture_white;
7622                         t->specularscale = r_shadow_gloss2intensity.value;
7623                         t->specularpower = r_shadow_gloss2exponent.value;
7624                 }
7625         }
7626         t->specularscale *= t->specularscalemod;
7627         t->specularpower *= t->specularpowermod;
7628
7629         // lightmaps mode looks bad with dlights using actual texturing, so turn
7630         // off the colormap and glossmap, but leave the normalmap on as it still
7631         // accurately represents the shading involved
7632         if (gl_lightmaps.integer)
7633         {
7634                 t->basetexture = r_texture_grey128;
7635                 t->pantstexture = r_texture_black;
7636                 t->shirttexture = r_texture_black;
7637                 t->nmaptexture = r_texture_blanknormalmap;
7638                 t->glosstexture = r_texture_black;
7639                 t->glowtexture = NULL;
7640                 t->fogtexture = NULL;
7641                 t->reflectmasktexture = NULL;
7642                 t->backgroundbasetexture = NULL;
7643                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7644                 t->backgroundglosstexture = r_texture_black;
7645                 t->backgroundglowtexture = NULL;
7646                 t->specularscale = 0;
7647                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7648         }
7649
7650         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7651         VectorClear(t->dlightcolor);
7652         t->currentnumlayers = 0;
7653         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7654         {
7655                 int blendfunc1, blendfunc2;
7656                 qboolean depthmask;
7657                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7658                 {
7659                         blendfunc1 = GL_SRC_ALPHA;
7660                         blendfunc2 = GL_ONE;
7661                 }
7662                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7663                 {
7664                         blendfunc1 = GL_SRC_ALPHA;
7665                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7666                 }
7667                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7668                 {
7669                         blendfunc1 = t->customblendfunc[0];
7670                         blendfunc2 = t->customblendfunc[1];
7671                 }
7672                 else
7673                 {
7674                         blendfunc1 = GL_ONE;
7675                         blendfunc2 = GL_ZERO;
7676                 }
7677                 // don't colormod evilblend textures
7678                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7679                         VectorSet(t->lightmapcolor, 1, 1, 1);
7680                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7681                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7682                 {
7683                         // fullbright is not affected by r_refdef.lightmapintensity
7684                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7685                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7686                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7687                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7688                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7689                 }
7690                 else
7691                 {
7692                         vec3_t ambientcolor;
7693                         float colorscale;
7694                         // set the color tint used for lights affecting this surface
7695                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7696                         colorscale = 2;
7697                         // q3bsp has no lightmap updates, so the lightstylevalue that
7698                         // would normally be baked into the lightmap must be
7699                         // applied to the color
7700                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7701                         if (model->type == mod_brushq3)
7702                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7703                         colorscale *= r_refdef.lightmapintensity;
7704                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7705                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7706                         // basic lit geometry
7707                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7708                         // add pants/shirt if needed
7709                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7710                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
7711                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7712                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7713                         // now add ambient passes if needed
7714                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7715                         {
7716                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
7717                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7718                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7719                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7720                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7721                         }
7722                 }
7723                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7724                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
7725                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7726                 {
7727                         // if this is opaque use alpha blend which will darken the earlier
7728                         // passes cheaply.
7729                         //
7730                         // if this is an alpha blended material, all the earlier passes
7731                         // were darkened by fog already, so we only need to add the fog
7732                         // color ontop through the fog mask texture
7733                         //
7734                         // if this is an additive blended material, all the earlier passes
7735                         // were darkened by fog already, and we should not add fog color
7736                         // (because the background was not darkened, there is no fog color
7737                         // that was lost behind it).
7738                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
7739                 }
7740         }
7741
7742         return t->currentframe;
7743 }
7744
7745 rsurfacestate_t rsurface;
7746
7747 void RSurf_ActiveWorldEntity(void)
7748 {
7749         dp_model_t *model = r_refdef.scene.worldmodel;
7750         //if (rsurface.entity == r_refdef.scene.worldentity)
7751         //      return;
7752         rsurface.entity = r_refdef.scene.worldentity;
7753         rsurface.skeleton = NULL;
7754         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7755         rsurface.ent_skinnum = 0;
7756         rsurface.ent_qwskin = -1;
7757         rsurface.ent_shadertime = 0;
7758         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7759         rsurface.matrix = identitymatrix;
7760         rsurface.inversematrix = identitymatrix;
7761         rsurface.matrixscale = 1;
7762         rsurface.inversematrixscale = 1;
7763         R_EntityMatrix(&identitymatrix);
7764         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7765         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7766         rsurface.fograngerecip = r_refdef.fograngerecip;
7767         rsurface.fogheightfade = r_refdef.fogheightfade;
7768         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7769         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7770         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7771         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7772         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7773         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7774         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7775         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7776         rsurface.colormod[3] = 1;
7777         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
7778         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7779         rsurface.frameblend[0].lerp = 1;
7780         rsurface.ent_alttextures = false;
7781         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7782         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7783         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7784         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7785         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7786         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7787         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7789         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7790         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7792         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7793         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7795         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7796         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7798         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7799         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7801         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7802         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7804         rsurface.modelelement3i = model->surfmesh.data_element3i;
7805         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7806         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7807         rsurface.modelelement3s = model->surfmesh.data_element3s;
7808         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7809         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7810         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7811         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7812         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7813         rsurface.modelsurfaces = model->data_surfaces;
7814         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7815         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7816         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7817         rsurface.modelgeneratedvertex = false;
7818         rsurface.batchgeneratedvertex = false;
7819         rsurface.batchfirstvertex = 0;
7820         rsurface.batchnumvertices = 0;
7821         rsurface.batchfirsttriangle = 0;
7822         rsurface.batchnumtriangles = 0;
7823         rsurface.batchvertex3f  = NULL;
7824         rsurface.batchvertex3f_vertexbuffer = NULL;
7825         rsurface.batchvertex3f_bufferoffset = 0;
7826         rsurface.batchsvector3f = NULL;
7827         rsurface.batchsvector3f_vertexbuffer = NULL;
7828         rsurface.batchsvector3f_bufferoffset = 0;
7829         rsurface.batchtvector3f = NULL;
7830         rsurface.batchtvector3f_vertexbuffer = NULL;
7831         rsurface.batchtvector3f_bufferoffset = 0;
7832         rsurface.batchnormal3f  = NULL;
7833         rsurface.batchnormal3f_vertexbuffer = NULL;
7834         rsurface.batchnormal3f_bufferoffset = 0;
7835         rsurface.batchlightmapcolor4f = NULL;
7836         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7837         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7838         rsurface.batchtexcoordtexture2f = NULL;
7839         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7840         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7841         rsurface.batchtexcoordlightmap2f = NULL;
7842         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7843         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7844         rsurface.batchvertexmesh = NULL;
7845         rsurface.batchvertexmeshbuffer = NULL;
7846         rsurface.batchvertex3fbuffer = NULL;
7847         rsurface.batchelement3i = NULL;
7848         rsurface.batchelement3i_indexbuffer = NULL;
7849         rsurface.batchelement3i_bufferoffset = 0;
7850         rsurface.batchelement3s = NULL;
7851         rsurface.batchelement3s_indexbuffer = NULL;
7852         rsurface.batchelement3s_bufferoffset = 0;
7853         rsurface.passcolor4f = NULL;
7854         rsurface.passcolor4f_vertexbuffer = NULL;
7855         rsurface.passcolor4f_bufferoffset = 0;
7856 }
7857
7858 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7859 {
7860         dp_model_t *model = ent->model;
7861         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7862         //      return;
7863         rsurface.entity = (entity_render_t *)ent;
7864         rsurface.skeleton = ent->skeleton;
7865         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7866         rsurface.ent_skinnum = ent->skinnum;
7867         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
7868         rsurface.ent_shadertime = ent->shadertime;
7869         rsurface.ent_flags = ent->flags;
7870         rsurface.matrix = ent->matrix;
7871         rsurface.inversematrix = ent->inversematrix;
7872         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874         R_EntityMatrix(&rsurface.matrix);
7875         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7882         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7883         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7884         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7885         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7886         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7887         rsurface.colormod[3] = ent->alpha;
7888         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7889         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7890         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7891         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7893         if (ent->model->brush.submodel && !prepass)
7894         {
7895                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7896                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7897         }
7898         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7899         {
7900                 if (ent->animcache_vertex3f)
7901                 {
7902                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7903                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7904                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7905                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7906                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7907                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7908                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7909                 }
7910                 else if (wanttangents)
7911                 {
7912                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7915                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7916                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7917                         rsurface.modelvertexmesh = NULL;
7918                         rsurface.modelvertexmeshbuffer = NULL;
7919                         rsurface.modelvertex3fbuffer = NULL;
7920                 }
7921                 else if (wantnormals)
7922                 {
7923                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924                         rsurface.modelsvector3f = NULL;
7925                         rsurface.modeltvector3f = NULL;
7926                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7928                         rsurface.modelvertexmesh = NULL;
7929                         rsurface.modelvertexmeshbuffer = NULL;
7930                         rsurface.modelvertex3fbuffer = NULL;
7931                 }
7932                 else
7933                 {
7934                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935                         rsurface.modelsvector3f = NULL;
7936                         rsurface.modeltvector3f = NULL;
7937                         rsurface.modelnormal3f = NULL;
7938                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7939                         rsurface.modelvertexmesh = NULL;
7940                         rsurface.modelvertexmeshbuffer = NULL;
7941                         rsurface.modelvertex3fbuffer = NULL;
7942                 }
7943                 rsurface.modelvertex3f_vertexbuffer = 0;
7944                 rsurface.modelvertex3f_bufferoffset = 0;
7945                 rsurface.modelsvector3f_vertexbuffer = 0;
7946                 rsurface.modelsvector3f_bufferoffset = 0;
7947                 rsurface.modeltvector3f_vertexbuffer = 0;
7948                 rsurface.modeltvector3f_bufferoffset = 0;
7949                 rsurface.modelnormal3f_vertexbuffer = 0;
7950                 rsurface.modelnormal3f_bufferoffset = 0;
7951                 rsurface.modelgeneratedvertex = true;
7952         }
7953         else
7954         {
7955                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7956                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7958                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7959                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7961                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7962                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7964                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7965                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7967                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7968                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7969                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7970                 rsurface.modelgeneratedvertex = false;
7971         }
7972         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7973         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7975         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7976         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7978         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7979         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7981         rsurface.modelelement3i = model->surfmesh.data_element3i;
7982         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7983         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7984         rsurface.modelelement3s = model->surfmesh.data_element3s;
7985         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7986         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7987         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7988         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7989         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7990         rsurface.modelsurfaces = model->data_surfaces;
7991         rsurface.batchgeneratedvertex = false;
7992         rsurface.batchfirstvertex = 0;
7993         rsurface.batchnumvertices = 0;
7994         rsurface.batchfirsttriangle = 0;
7995         rsurface.batchnumtriangles = 0;
7996         rsurface.batchvertex3f  = NULL;
7997         rsurface.batchvertex3f_vertexbuffer = NULL;
7998         rsurface.batchvertex3f_bufferoffset = 0;
7999         rsurface.batchsvector3f = NULL;
8000         rsurface.batchsvector3f_vertexbuffer = NULL;
8001         rsurface.batchsvector3f_bufferoffset = 0;
8002         rsurface.batchtvector3f = NULL;
8003         rsurface.batchtvector3f_vertexbuffer = NULL;
8004         rsurface.batchtvector3f_bufferoffset = 0;
8005         rsurface.batchnormal3f  = NULL;
8006         rsurface.batchnormal3f_vertexbuffer = NULL;
8007         rsurface.batchnormal3f_bufferoffset = 0;
8008         rsurface.batchlightmapcolor4f = NULL;
8009         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8010         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8011         rsurface.batchtexcoordtexture2f = NULL;
8012         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8013         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8014         rsurface.batchtexcoordlightmap2f = NULL;
8015         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8016         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8017         rsurface.batchvertexmesh = NULL;
8018         rsurface.batchvertexmeshbuffer = NULL;
8019         rsurface.batchvertex3fbuffer = NULL;
8020         rsurface.batchelement3i = NULL;
8021         rsurface.batchelement3i_indexbuffer = NULL;
8022         rsurface.batchelement3i_bufferoffset = 0;
8023         rsurface.batchelement3s = NULL;
8024         rsurface.batchelement3s_indexbuffer = NULL;
8025         rsurface.batchelement3s_bufferoffset = 0;
8026         rsurface.passcolor4f = NULL;
8027         rsurface.passcolor4f_vertexbuffer = NULL;
8028         rsurface.passcolor4f_bufferoffset = 0;
8029 }
8030
8031 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8032 {
8033         rsurface.entity = r_refdef.scene.worldentity;
8034         rsurface.skeleton = NULL;
8035         rsurface.ent_skinnum = 0;
8036         rsurface.ent_qwskin = -1;
8037         rsurface.ent_shadertime = shadertime;
8038         rsurface.ent_flags = entflags;
8039         rsurface.modelnumvertices = numvertices;
8040         rsurface.modelnumtriangles = numtriangles;
8041         rsurface.matrix = *matrix;
8042         rsurface.inversematrix = *inversematrix;
8043         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8044         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8045         R_EntityMatrix(&rsurface.matrix);
8046         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8047         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8048         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8049         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8050         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8051         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8052         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8053         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8054         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8055         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8056         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8057         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8058         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8059         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8060         rsurface.frameblend[0].lerp = 1;
8061         rsurface.ent_alttextures = false;
8062         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8063         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8064         if (wanttangents)
8065         {
8066                 rsurface.modelvertex3f = (float *)vertex3f;
8067                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8069                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8070         }
8071         else if (wantnormals)
8072         {
8073                 rsurface.modelvertex3f = (float *)vertex3f;
8074                 rsurface.modelsvector3f = NULL;
8075                 rsurface.modeltvector3f = NULL;
8076                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8077         }
8078         else
8079         {
8080                 rsurface.modelvertex3f = (float *)vertex3f;
8081                 rsurface.modelsvector3f = NULL;
8082                 rsurface.modeltvector3f = NULL;
8083                 rsurface.modelnormal3f = NULL;
8084         }
8085         rsurface.modelvertexmesh = NULL;
8086         rsurface.modelvertexmeshbuffer = NULL;
8087         rsurface.modelvertex3fbuffer = NULL;
8088         rsurface.modelvertex3f_vertexbuffer = 0;
8089         rsurface.modelvertex3f_bufferoffset = 0;
8090         rsurface.modelsvector3f_vertexbuffer = 0;
8091         rsurface.modelsvector3f_bufferoffset = 0;
8092         rsurface.modeltvector3f_vertexbuffer = 0;
8093         rsurface.modeltvector3f_bufferoffset = 0;
8094         rsurface.modelnormal3f_vertexbuffer = 0;
8095         rsurface.modelnormal3f_bufferoffset = 0;
8096         rsurface.modelgeneratedvertex = true;
8097         rsurface.modellightmapcolor4f  = (float *)color4f;
8098         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8099         rsurface.modellightmapcolor4f_bufferoffset = 0;
8100         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8101         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8102         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8103         rsurface.modeltexcoordlightmap2f  = NULL;
8104         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8105         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8106         rsurface.modelelement3i = (int *)element3i;
8107         rsurface.modelelement3i_indexbuffer = NULL;
8108         rsurface.modelelement3i_bufferoffset = 0;
8109         rsurface.modelelement3s = (unsigned short *)element3s;
8110         rsurface.modelelement3s_indexbuffer = NULL;
8111         rsurface.modelelement3s_bufferoffset = 0;
8112         rsurface.modellightmapoffsets = NULL;
8113         rsurface.modelsurfaces = NULL;
8114         rsurface.batchgeneratedvertex = false;
8115         rsurface.batchfirstvertex = 0;
8116         rsurface.batchnumvertices = 0;
8117         rsurface.batchfirsttriangle = 0;
8118         rsurface.batchnumtriangles = 0;
8119         rsurface.batchvertex3f  = NULL;
8120         rsurface.batchvertex3f_vertexbuffer = NULL;
8121         rsurface.batchvertex3f_bufferoffset = 0;
8122         rsurface.batchsvector3f = NULL;
8123         rsurface.batchsvector3f_vertexbuffer = NULL;
8124         rsurface.batchsvector3f_bufferoffset = 0;
8125         rsurface.batchtvector3f = NULL;
8126         rsurface.batchtvector3f_vertexbuffer = NULL;
8127         rsurface.batchtvector3f_bufferoffset = 0;
8128         rsurface.batchnormal3f  = NULL;
8129         rsurface.batchnormal3f_vertexbuffer = NULL;
8130         rsurface.batchnormal3f_bufferoffset = 0;
8131         rsurface.batchlightmapcolor4f = NULL;
8132         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8133         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8134         rsurface.batchtexcoordtexture2f = NULL;
8135         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8136         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8137         rsurface.batchtexcoordlightmap2f = NULL;
8138         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8139         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8140         rsurface.batchvertexmesh = NULL;
8141         rsurface.batchvertexmeshbuffer = NULL;
8142         rsurface.batchvertex3fbuffer = NULL;
8143         rsurface.batchelement3i = NULL;
8144         rsurface.batchelement3i_indexbuffer = NULL;
8145         rsurface.batchelement3i_bufferoffset = 0;
8146         rsurface.batchelement3s = NULL;
8147         rsurface.batchelement3s_indexbuffer = NULL;
8148         rsurface.batchelement3s_bufferoffset = 0;
8149         rsurface.passcolor4f = NULL;
8150         rsurface.passcolor4f_vertexbuffer = NULL;
8151         rsurface.passcolor4f_bufferoffset = 0;
8152
8153         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8154         {
8155                 if ((wantnormals || wanttangents) && !normal3f)
8156                 {
8157                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8158                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8159                 }
8160                 if (wanttangents && !svector3f)
8161                 {
8162                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8164                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8165                 }
8166         }
8167 }
8168
8169 float RSurf_FogPoint(const float *v)
8170 {
8171         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8172         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8173         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8174         float FogHeightFade = r_refdef.fogheightfade;
8175         float fogfrac;
8176         unsigned int fogmasktableindex;
8177         if (r_refdef.fogplaneviewabove)
8178                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8179         else
8180                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8181         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8182         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8183 }
8184
8185 float RSurf_FogVertex(const float *v)
8186 {
8187         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8188         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8189         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8190         float FogHeightFade = rsurface.fogheightfade;
8191         float fogfrac;
8192         unsigned int fogmasktableindex;
8193         if (r_refdef.fogplaneviewabove)
8194                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8195         else
8196                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8197         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8198         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8199 }
8200
8201 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8202 {
8203         int i;
8204         for (i = 0;i < numelements;i++)
8205                 outelement3i[i] = inelement3i[i] + adjust;
8206 }
8207
8208 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8209 extern cvar_t gl_vbo;
8210 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8211 {
8212         int deformindex;
8213         int firsttriangle;
8214         int numtriangles;
8215         int firstvertex;
8216         int endvertex;
8217         int numvertices;
8218         int surfacefirsttriangle;
8219         int surfacenumtriangles;
8220         int surfacefirstvertex;
8221         int surfaceendvertex;
8222         int surfacenumvertices;
8223         int batchnumvertices;
8224         int batchnumtriangles;
8225         int needsupdate;
8226         int i, j;
8227         qboolean gaps;
8228         qboolean dynamicvertex;
8229         float amplitude;
8230         float animpos;
8231         float scale;
8232         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8233         float waveparms[4];
8234         q3shaderinfo_deform_t *deform;
8235         const msurface_t *surface, *firstsurface;
8236         r_vertexmesh_t *vertexmesh;
8237         if (!texturenumsurfaces)
8238                 return;
8239         // find vertex range of this surface batch
8240         gaps = false;
8241         firstsurface = texturesurfacelist[0];
8242         firsttriangle = firstsurface->num_firsttriangle;
8243         batchnumvertices = 0;
8244         batchnumtriangles = 0;
8245         firstvertex = endvertex = firstsurface->num_firstvertex;
8246         for (i = 0;i < texturenumsurfaces;i++)
8247         {
8248                 surface = texturesurfacelist[i];
8249                 if (surface != firstsurface + i)
8250                         gaps = true;
8251                 surfacefirstvertex = surface->num_firstvertex;
8252                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8253                 surfacenumvertices = surface->num_vertices;
8254                 surfacenumtriangles = surface->num_triangles;
8255                 if (firstvertex > surfacefirstvertex)
8256                         firstvertex = surfacefirstvertex;
8257                 if (endvertex < surfaceendvertex)
8258                         endvertex = surfaceendvertex;
8259                 batchnumvertices += surfacenumvertices;
8260                 batchnumtriangles += surfacenumtriangles;
8261         }
8262
8263         // we now know the vertex range used, and if there are any gaps in it
8264         rsurface.batchfirstvertex = firstvertex;
8265         rsurface.batchnumvertices = endvertex - firstvertex;
8266         rsurface.batchfirsttriangle = firsttriangle;
8267         rsurface.batchnumtriangles = batchnumtriangles;
8268
8269         // this variable holds flags for which properties have been updated that
8270         // may require regenerating vertexmesh array...
8271         needsupdate = 0;
8272
8273         // check if any dynamic vertex processing must occur
8274         dynamicvertex = false;
8275
8276         // if there is a chance of animated vertex colors, it's a dynamic batch
8277         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8278         {
8279                 dynamicvertex = true;
8280                 batchneed |= BATCHNEED_NOGAPS;
8281                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8282         }
8283
8284         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8285         {
8286                 switch (deform->deform)
8287                 {
8288                 default:
8289                 case Q3DEFORM_PROJECTIONSHADOW:
8290                 case Q3DEFORM_TEXT0:
8291                 case Q3DEFORM_TEXT1:
8292                 case Q3DEFORM_TEXT2:
8293                 case Q3DEFORM_TEXT3:
8294                 case Q3DEFORM_TEXT4:
8295                 case Q3DEFORM_TEXT5:
8296                 case Q3DEFORM_TEXT6:
8297                 case Q3DEFORM_TEXT7:
8298                 case Q3DEFORM_NONE:
8299                         break;
8300                 case Q3DEFORM_AUTOSPRITE:
8301                         dynamicvertex = true;
8302                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8303                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8304                         break;
8305                 case Q3DEFORM_AUTOSPRITE2:
8306                         dynamicvertex = true;
8307                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8309                         break;
8310                 case Q3DEFORM_NORMAL:
8311                         dynamicvertex = true;
8312                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8314                         break;
8315                 case Q3DEFORM_WAVE:
8316                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8317                                 break; // if wavefunc is a nop, ignore this transform
8318                         dynamicvertex = true;
8319                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8320                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8321                         break;
8322                 case Q3DEFORM_BULGE:
8323                         dynamicvertex = true;
8324                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8326                         break;
8327                 case Q3DEFORM_MOVE:
8328                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8329                                 break; // if wavefunc is a nop, ignore this transform
8330                         dynamicvertex = true;
8331                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8332                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8333                         break;
8334                 }
8335         }
8336         switch(rsurface.texture->tcgen.tcgen)
8337         {
8338         default:
8339         case Q3TCGEN_TEXTURE:
8340                 break;
8341         case Q3TCGEN_LIGHTMAP:
8342                 dynamicvertex = true;
8343                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8344                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8345                 break;
8346         case Q3TCGEN_VECTOR:
8347                 dynamicvertex = true;
8348                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8349                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8350                 break;
8351         case Q3TCGEN_ENVIRONMENT:
8352                 dynamicvertex = true;
8353                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8354                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8355                 break;
8356         }
8357         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8358         {
8359                 dynamicvertex = true;
8360                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8361                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8362         }
8363
8364         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8365         {
8366                 dynamicvertex = true;
8367                 batchneed |= BATCHNEED_NOGAPS;
8368                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8369         }
8370
8371         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8372         {
8373                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8374                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8375                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8376                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8377                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8378                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8379                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8380         }
8381
8382         // when the model data has no vertex buffer (dynamic mesh), we need to
8383         // eliminate gaps
8384         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8385                 batchneed |= BATCHNEED_NOGAPS;
8386
8387         // if needsupdate, we have to do a dynamic vertex batch for sure
8388         if (needsupdate & batchneed)
8389                 dynamicvertex = true;
8390
8391         // see if we need to build vertexmesh from arrays
8392         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8393                 dynamicvertex = true;
8394
8395         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8396         // also some drivers strongly dislike firstvertex
8397         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8398                 dynamicvertex = true;
8399
8400         rsurface.batchvertex3f = rsurface.modelvertex3f;
8401         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8402         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8403         rsurface.batchsvector3f = rsurface.modelsvector3f;
8404         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8405         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8406         rsurface.batchtvector3f = rsurface.modeltvector3f;
8407         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8408         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8409         rsurface.batchnormal3f = rsurface.modelnormal3f;
8410         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8411         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8412         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8413         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8414         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8415         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8416         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8417         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8418         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8419         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8420         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8421         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8422         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8423         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8424         rsurface.batchelement3i = rsurface.modelelement3i;
8425         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8426         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8427         rsurface.batchelement3s = rsurface.modelelement3s;
8428         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8429         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8430
8431         // if any dynamic vertex processing has to occur in software, we copy the
8432         // entire surface list together before processing to rebase the vertices
8433         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8434         //
8435         // if any gaps exist and we do not have a static vertex buffer, we have to
8436         // copy the surface list together to avoid wasting upload bandwidth on the
8437         // vertices in the gaps.
8438         //
8439         // if gaps exist and we have a static vertex buffer, we still have to
8440         // combine the index buffer ranges into one dynamic index buffer.
8441         //
8442         // in all cases we end up with data that can be drawn in one call.
8443
8444         if (!dynamicvertex)
8445         {
8446                 // static vertex data, just set pointers...
8447                 rsurface.batchgeneratedvertex = false;
8448                 // if there are gaps, we want to build a combined index buffer,
8449                 // otherwise use the original static buffer with an appropriate offset
8450                 if (gaps)
8451                 {
8452                         // build a new triangle elements array for this batch
8453                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8454                         rsurface.batchfirsttriangle = 0;
8455                         numtriangles = 0;
8456                         for (i = 0;i < texturenumsurfaces;i++)
8457                         {
8458                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8459                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8460                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8461                                 numtriangles += surfacenumtriangles;
8462                         }
8463                         rsurface.batchelement3i_indexbuffer = NULL;
8464                         rsurface.batchelement3i_bufferoffset = 0;
8465                         rsurface.batchelement3s = NULL;
8466                         rsurface.batchelement3s_indexbuffer = NULL;
8467                         rsurface.batchelement3s_bufferoffset = 0;
8468                         if (endvertex <= 65536)
8469                         {
8470                                 // make a 16bit (unsigned short) index array if possible
8471                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8472                                 for (i = 0;i < numtriangles*3;i++)
8473                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8474                         }
8475                 }
8476                 return;
8477         }
8478
8479         // something needs software processing, do it for real...
8480         // we only directly handle separate array data in this case and then
8481         // generate interleaved data if needed...
8482         rsurface.batchgeneratedvertex = true;
8483
8484         // now copy the vertex data into a combined array and make an index array
8485         // (this is what Quake3 does all the time)
8486         //if (gaps || rsurface.batchfirstvertex)
8487         {
8488                 rsurface.batchvertex3fbuffer = NULL;
8489                 rsurface.batchvertexmesh = NULL;
8490                 rsurface.batchvertexmeshbuffer = NULL;
8491                 rsurface.batchvertex3f = NULL;
8492                 rsurface.batchvertex3f_vertexbuffer = NULL;
8493                 rsurface.batchvertex3f_bufferoffset = 0;
8494                 rsurface.batchsvector3f = NULL;
8495                 rsurface.batchsvector3f_vertexbuffer = NULL;
8496                 rsurface.batchsvector3f_bufferoffset = 0;
8497                 rsurface.batchtvector3f = NULL;
8498                 rsurface.batchtvector3f_vertexbuffer = NULL;
8499                 rsurface.batchtvector3f_bufferoffset = 0;
8500                 rsurface.batchnormal3f = NULL;
8501                 rsurface.batchnormal3f_vertexbuffer = NULL;
8502                 rsurface.batchnormal3f_bufferoffset = 0;
8503                 rsurface.batchlightmapcolor4f = NULL;
8504                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8505                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8506                 rsurface.batchtexcoordtexture2f = NULL;
8507                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8508                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8509                 rsurface.batchtexcoordlightmap2f = NULL;
8510                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8511                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8512                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8513                 rsurface.batchelement3i_indexbuffer = NULL;
8514                 rsurface.batchelement3i_bufferoffset = 0;
8515                 rsurface.batchelement3s = NULL;
8516                 rsurface.batchelement3s_indexbuffer = NULL;
8517                 rsurface.batchelement3s_bufferoffset = 0;
8518                 // we'll only be setting up certain arrays as needed
8519                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8520                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8521                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8522                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8524                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8525                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8526                 {
8527                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8529                 }
8530                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8531                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8532                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8533                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8535                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8536                 numvertices = 0;
8537                 numtriangles = 0;
8538                 for (i = 0;i < texturenumsurfaces;i++)
8539                 {
8540                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8541                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8542                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8543                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8544                         // copy only the data requested
8545                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8546                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8547                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8548                         {
8549                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8550                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8552                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8553                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8554                                 {
8555                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8557                                 }
8558                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8559                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8560                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8561                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8562                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8563                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8564                         }
8565                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8566                         numvertices += surfacenumvertices;
8567                         numtriangles += surfacenumtriangles;
8568                 }
8569
8570                 // generate a 16bit index array as well if possible
8571                 // (in general, dynamic batches fit)
8572                 if (numvertices <= 65536)
8573                 {
8574                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575                         for (i = 0;i < numtriangles*3;i++)
8576                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8577                 }
8578
8579                 // since we've copied everything, the batch now starts at 0
8580                 rsurface.batchfirstvertex = 0;
8581                 rsurface.batchnumvertices = batchnumvertices;
8582                 rsurface.batchfirsttriangle = 0;
8583                 rsurface.batchnumtriangles = batchnumtriangles;
8584         }
8585
8586         // q1bsp surfaces rendered in vertex color mode have to have colors
8587         // calculated based on lightstyles
8588         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8589         {
8590                 // generate color arrays for the surfaces in this list
8591                 int c[4];
8592                 int scale;
8593                 int size3;
8594                 const int *offsets;
8595                 const unsigned char *lm;
8596                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8597                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8599                 numvertices = 0;
8600                 for (i = 0;i < texturenumsurfaces;i++)
8601                 {
8602                         surface = texturesurfacelist[i];
8603                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8604                         surfacenumvertices = surface->num_vertices;
8605                         if (surface->lightmapinfo->samples)
8606                         {
8607                                 for (j = 0;j < surfacenumvertices;j++)
8608                                 {
8609                                         lm = surface->lightmapinfo->samples + offsets[j];
8610                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8611                                         VectorScale(lm, scale, c);
8612                                         if (surface->lightmapinfo->styles[1] != 255)
8613                                         {
8614                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8615                                                 lm += size3;
8616                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8617                                                 VectorMA(c, scale, lm, c);
8618                                                 if (surface->lightmapinfo->styles[2] != 255)
8619                                                 {
8620                                                         lm += size3;
8621                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8622                                                         VectorMA(c, scale, lm, c);
8623                                                         if (surface->lightmapinfo->styles[3] != 255)
8624                                                         {
8625                                                                 lm += size3;
8626                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8627                                                                 VectorMA(c, scale, lm, c);
8628                                                         }
8629                                                 }
8630                                         }
8631                                         c[0] >>= 7;
8632                                         c[1] >>= 7;
8633                                         c[2] >>= 7;
8634                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
8635                                         numvertices++;
8636                                 }
8637                         }
8638                         else
8639                         {
8640                                 for (j = 0;j < surfacenumvertices;j++)
8641                                 {
8642                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8643                                         numvertices++;
8644                                 }
8645                         }
8646                 }
8647         }
8648
8649         // if vertices are deformed (sprite flares and things in maps, possibly
8650         // water waves, bulges and other deformations), modify the copied vertices
8651         // in place
8652         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8653         {
8654                 switch (deform->deform)
8655                 {
8656                 default:
8657                 case Q3DEFORM_PROJECTIONSHADOW:
8658                 case Q3DEFORM_TEXT0:
8659                 case Q3DEFORM_TEXT1:
8660                 case Q3DEFORM_TEXT2:
8661                 case Q3DEFORM_TEXT3:
8662                 case Q3DEFORM_TEXT4:
8663                 case Q3DEFORM_TEXT5:
8664                 case Q3DEFORM_TEXT6:
8665                 case Q3DEFORM_TEXT7:
8666                 case Q3DEFORM_NONE:
8667                         break;
8668                 case Q3DEFORM_AUTOSPRITE:
8669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672                         VectorNormalize(newforward);
8673                         VectorNormalize(newright);
8674                         VectorNormalize(newup);
8675 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8677 //                      rsurface.batchvertex3f_bufferoffset = 0;
8678 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8679 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8680 //                      rsurface.batchsvector3f_bufferoffset = 0;
8681 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8682 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8683 //                      rsurface.batchtvector3f_bufferoffset = 0;
8684 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8686 //                      rsurface.batchnormal3f_bufferoffset = 0;
8687                         // a single autosprite surface can contain multiple sprites...
8688                         for (j = 0;j < batchnumvertices - 3;j += 4)
8689                         {
8690                                 VectorClear(center);
8691                                 for (i = 0;i < 4;i++)
8692                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8693                                 VectorScale(center, 0.25f, center);
8694                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8695                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8696                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8697                                 for (i = 0;i < 4;i++)
8698                                 {
8699                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8700                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8701                                 }
8702                         }
8703                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8704                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8705                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8706                         break;
8707                 case Q3DEFORM_AUTOSPRITE2:
8708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8709                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8710                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8711                         VectorNormalize(newforward);
8712                         VectorNormalize(newright);
8713                         VectorNormalize(newup);
8714 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8715 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8716 //                      rsurface.batchvertex3f_bufferoffset = 0;
8717                         {
8718                                 const float *v1, *v2;
8719                                 vec3_t start, end;
8720                                 float f, l;
8721                                 struct
8722                                 {
8723                                         float length2;
8724                                         const float *v1;
8725                                         const float *v2;
8726                                 }
8727                                 shortest[2];
8728                                 memset(shortest, 0, sizeof(shortest));
8729                                 // a single autosprite surface can contain multiple sprites...
8730                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8731                                 {
8732                                         VectorClear(center);
8733                                         for (i = 0;i < 4;i++)
8734                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8735                                         VectorScale(center, 0.25f, center);
8736                                         // find the two shortest edges, then use them to define the
8737                                         // axis vectors for rotating around the central axis
8738                                         for (i = 0;i < 6;i++)
8739                                         {
8740                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8741                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8742                                                 l = VectorDistance2(v1, v2);
8743                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8744                                                 if (v1[2] != v2[2])
8745                                                         l += (1.0f / 1024.0f);
8746                                                 if (shortest[0].length2 > l || i == 0)
8747                                                 {
8748                                                         shortest[1] = shortest[0];
8749                                                         shortest[0].length2 = l;
8750                                                         shortest[0].v1 = v1;
8751                                                         shortest[0].v2 = v2;
8752                                                 }
8753                                                 else if (shortest[1].length2 > l || i == 1)
8754                                                 {
8755                                                         shortest[1].length2 = l;
8756                                                         shortest[1].v1 = v1;
8757                                                         shortest[1].v2 = v2;
8758                                                 }
8759                                         }
8760                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8761                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8762                                         // this calculates the right vector from the shortest edge
8763                                         // and the up vector from the edge midpoints
8764                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8765                                         VectorNormalize(right);
8766                                         VectorSubtract(end, start, up);
8767                                         VectorNormalize(up);
8768                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8769                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8770                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8771                                         VectorNegate(forward, forward);
8772                                         VectorReflect(forward, 0, up, forward);
8773                                         VectorNormalize(forward);
8774                                         CrossProduct(up, forward, newright);
8775                                         VectorNormalize(newright);
8776                                         // rotate the quad around the up axis vector, this is made
8777                                         // especially easy by the fact we know the quad is flat,
8778                                         // so we only have to subtract the center position and
8779                                         // measure distance along the right vector, and then
8780                                         // multiply that by the newright vector and add back the
8781                                         // center position
8782                                         // we also need to subtract the old position to undo the
8783                                         // displacement from the center, which we do with a
8784                                         // DotProduct, the subtraction/addition of center is also
8785                                         // optimized into DotProducts here
8786                                         l = DotProduct(right, center);
8787                                         for (i = 0;i < 4;i++)
8788                                         {
8789                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8790                                                 f = DotProduct(right, v1) - l;
8791                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8792                                         }
8793                                 }
8794                         }
8795                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8796                         {
8797 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8799 //                              rsurface.batchnormal3f_bufferoffset = 0;
8800                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8801                         }
8802                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8803                         {
8804 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8806 //                              rsurface.batchsvector3f_bufferoffset = 0;
8807 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8809 //                              rsurface.batchtvector3f_bufferoffset = 0;
8810                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8811                         }
8812                         break;
8813                 case Q3DEFORM_NORMAL:
8814                         // deform the normals to make reflections wavey
8815                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8816                         rsurface.batchnormal3f_vertexbuffer = NULL;
8817                         rsurface.batchnormal3f_bufferoffset = 0;
8818                         for (j = 0;j < batchnumvertices;j++)
8819                         {
8820                                 float vertex[3];
8821                                 float *normal = rsurface.batchnormal3f + 3*j;
8822                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8823                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8824                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8825                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8826                                 VectorNormalize(normal);
8827                         }
8828                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8829                         {
8830 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8831 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8832 //                              rsurface.batchsvector3f_bufferoffset = 0;
8833 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8835 //                              rsurface.batchtvector3f_bufferoffset = 0;
8836                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8837                         }
8838                         break;
8839                 case Q3DEFORM_WAVE:
8840                         // deform vertex array to make wavey water and flags and such
8841                         waveparms[0] = deform->waveparms[0];
8842                         waveparms[1] = deform->waveparms[1];
8843                         waveparms[2] = deform->waveparms[2];
8844                         waveparms[3] = deform->waveparms[3];
8845                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8846                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8847                         // this is how a divisor of vertex influence on deformation
8848                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8849                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8850 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8851 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8852 //                      rsurface.batchvertex3f_bufferoffset = 0;
8853 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8854 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8855 //                      rsurface.batchnormal3f_bufferoffset = 0;
8856                         for (j = 0;j < batchnumvertices;j++)
8857                         {
8858                                 // if the wavefunc depends on time, evaluate it per-vertex
8859                                 if (waveparms[3])
8860                                 {
8861                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8862                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8863                                 }
8864                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8865                         }
8866                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8867                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8868                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8869                         {
8870 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8872 //                              rsurface.batchsvector3f_bufferoffset = 0;
8873 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8875 //                              rsurface.batchtvector3f_bufferoffset = 0;
8876                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8877                         }
8878                         break;
8879                 case Q3DEFORM_BULGE:
8880                         // deform vertex array to make the surface have moving bulges
8881 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8882 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8883 //                      rsurface.batchvertex3f_bufferoffset = 0;
8884 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8885 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8886 //                      rsurface.batchnormal3f_bufferoffset = 0;
8887                         for (j = 0;j < batchnumvertices;j++)
8888                         {
8889                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8890                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8891                         }
8892                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8893                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8894                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8895                         {
8896 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8897 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8898 //                              rsurface.batchsvector3f_bufferoffset = 0;
8899 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8901 //                              rsurface.batchtvector3f_bufferoffset = 0;
8902                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8903                         }
8904                         break;
8905                 case Q3DEFORM_MOVE:
8906                         // deform vertex array
8907                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8908                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8909                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8910                         VectorScale(deform->parms, scale, waveparms);
8911 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8912 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8913 //                      rsurface.batchvertex3f_bufferoffset = 0;
8914                         for (j = 0;j < batchnumvertices;j++)
8915                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8916                         break;
8917                 }
8918         }
8919
8920         // generate texcoords based on the chosen texcoord source
8921         switch(rsurface.texture->tcgen.tcgen)
8922         {
8923         default:
8924         case Q3TCGEN_TEXTURE:
8925                 break;
8926         case Q3TCGEN_LIGHTMAP:
8927 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8928 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930                 if (rsurface.batchtexcoordlightmap2f)
8931                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8932                 break;
8933         case Q3TCGEN_VECTOR:
8934 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8935 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8936 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8937                 for (j = 0;j < batchnumvertices;j++)
8938                 {
8939                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8940                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8941                 }
8942                 break;
8943         case Q3TCGEN_ENVIRONMENT:
8944                 // make environment reflections using a spheremap
8945                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948                 for (j = 0;j < batchnumvertices;j++)
8949                 {
8950                         // identical to Q3A's method, but executed in worldspace so
8951                         // carried models can be shiny too
8952
8953                         float viewer[3], d, reflected[3], worldreflected[3];
8954
8955                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8956                         // VectorNormalize(viewer);
8957
8958                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8959
8960                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8961                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8962                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8963                         // note: this is proportinal to viewer, so we can normalize later
8964
8965                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8966                         VectorNormalize(worldreflected);
8967
8968                         // note: this sphere map only uses world x and z!
8969                         // so positive and negative y will LOOK THE SAME.
8970                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8971                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8972                 }
8973                 break;
8974         }
8975         // the only tcmod that needs software vertex processing is turbulent, so
8976         // check for it here and apply the changes if needed
8977         // and we only support that as the first one
8978         // (handling a mixture of turbulent and other tcmods would be problematic
8979         //  without punting it entirely to a software path)
8980         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8981         {
8982                 amplitude = rsurface.texture->tcmods[0].parms[1];
8983                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8984 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8985 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8986 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8987                 for (j = 0;j < batchnumvertices;j++)
8988                 {
8989                         rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8990                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8991                 }
8992         }
8993
8994         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8995         {
8996                 // convert the modified arrays to vertex structs
8997 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8998 //              rsurface.batchvertexmeshbuffer = NULL;
8999                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9000                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9001                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9002                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9003                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9005                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9006                 {
9007                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9008                         {
9009                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9010                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9011                         }
9012                 }
9013                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9014                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9016                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9017                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9018                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9019                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9020                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9021                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9022         }
9023 }
9024
9025 void RSurf_DrawBatch(void)
9026 {
9027         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9028         // through the pipeline, killing it earlier in the pipeline would have
9029         // per-surface overhead rather than per-batch overhead, so it's best to
9030         // reject it here, before it hits glDraw.
9031         if (rsurface.batchnumtriangles == 0)
9032                 return;
9033 #if 0
9034         // batch debugging code
9035         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9036         {
9037                 int i;
9038                 int j;
9039                 int c;
9040                 const int *e;
9041                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9042                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9043                 {
9044                         c = e[i];
9045                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9046                         {
9047                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9048                                 {
9049                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9050                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
9051                                         break;
9052                                 }
9053                         }
9054                 }
9055         }
9056 #endif
9057         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9058 }
9059
9060 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9061 {
9062         // pick the closest matching water plane
9063         int planeindex, vertexindex, bestplaneindex = -1;
9064         float d, bestd;
9065         vec3_t vert;
9066         const float *v;
9067         r_waterstate_waterplane_t *p;
9068         qboolean prepared = false;
9069         bestd = 0;
9070         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9071         {
9072                 if(p->camera_entity != rsurface.texture->camera_entity)
9073                         continue;
9074                 d = 0;
9075                 if(!prepared)
9076                 {
9077                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9078                         prepared = true;
9079                         if(rsurface.batchnumvertices == 0)
9080                                 break;
9081                 }
9082                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9083                 {
9084                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9085                         d += fabs(PlaneDiff(vert, &p->plane));
9086                 }
9087                 if (bestd > d || bestplaneindex < 0)
9088                 {
9089                         bestd = d;
9090                         bestplaneindex = planeindex;
9091                 }
9092         }
9093         return bestplaneindex;
9094         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9095         // this situation though, as it might be better to render single larger
9096         // batches with useless stuff (backface culled for example) than to
9097         // render multiple smaller batches
9098 }
9099
9100 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9101 {
9102         int i;
9103         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9104         rsurface.passcolor4f_vertexbuffer = 0;
9105         rsurface.passcolor4f_bufferoffset = 0;
9106         for (i = 0;i < rsurface.batchnumvertices;i++)
9107                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9108 }
9109
9110 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9111 {
9112         int i;
9113         float f;
9114         const float *v;
9115         const float *c;
9116         float *c2;
9117         if (rsurface.passcolor4f)
9118         {
9119                 // generate color arrays
9120                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9121                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9122                 rsurface.passcolor4f_vertexbuffer = 0;
9123                 rsurface.passcolor4f_bufferoffset = 0;
9124                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9125                 {
9126                         f = RSurf_FogVertex(v);
9127                         c2[0] = c[0] * f;
9128                         c2[1] = c[1] * f;
9129                         c2[2] = c[2] * f;
9130                         c2[3] = c[3];
9131                 }
9132         }
9133         else
9134         {
9135                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9136                 rsurface.passcolor4f_vertexbuffer = 0;
9137                 rsurface.passcolor4f_bufferoffset = 0;
9138                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9139                 {
9140                         f = RSurf_FogVertex(v);
9141                         c2[0] = f;
9142                         c2[1] = f;
9143                         c2[2] = f;
9144                         c2[3] = 1;
9145                 }
9146         }
9147 }
9148
9149 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9150 {
9151         int i;
9152         float f;
9153         const float *v;
9154         const float *c;
9155         float *c2;
9156         if (!rsurface.passcolor4f)
9157                 return;
9158         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9159         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9160         rsurface.passcolor4f_vertexbuffer = 0;
9161         rsurface.passcolor4f_bufferoffset = 0;
9162         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9163         {
9164                 f = RSurf_FogVertex(v);
9165                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9166                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9167                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9168                 c2[3] = c[3];
9169         }
9170 }
9171
9172 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9173 {
9174         int i;
9175         const float *c;
9176         float *c2;
9177         if (!rsurface.passcolor4f)
9178                 return;
9179         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9180         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9181         rsurface.passcolor4f_vertexbuffer = 0;
9182         rsurface.passcolor4f_bufferoffset = 0;
9183         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9184         {
9185                 c2[0] = c[0] * r;
9186                 c2[1] = c[1] * g;
9187                 c2[2] = c[2] * b;
9188                 c2[3] = c[3] * a;
9189         }
9190 }
9191
9192 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9193 {
9194         int i;
9195         const float *c;
9196         float *c2;
9197         if (!rsurface.passcolor4f)
9198                 return;
9199         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9200         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9201         rsurface.passcolor4f_vertexbuffer = 0;
9202         rsurface.passcolor4f_bufferoffset = 0;
9203         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9204         {
9205                 c2[0] = c[0] + r_refdef.scene.ambient;
9206                 c2[1] = c[1] + r_refdef.scene.ambient;
9207                 c2[2] = c[2] + r_refdef.scene.ambient;
9208                 c2[3] = c[3];
9209         }
9210 }
9211
9212 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9213 {
9214         // TODO: optimize
9215         rsurface.passcolor4f = NULL;
9216         rsurface.passcolor4f_vertexbuffer = 0;
9217         rsurface.passcolor4f_bufferoffset = 0;
9218         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9219         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9220         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9221         GL_Color(r, g, b, a);
9222         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9223         RSurf_DrawBatch();
9224 }
9225
9226 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9227 {
9228         // TODO: optimize applyfog && applycolor case
9229         // just apply fog if necessary, and tint the fog color array if necessary
9230         rsurface.passcolor4f = NULL;
9231         rsurface.passcolor4f_vertexbuffer = 0;
9232         rsurface.passcolor4f_bufferoffset = 0;
9233         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9234         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9235         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9236         GL_Color(r, g, b, a);
9237         RSurf_DrawBatch();
9238 }
9239
9240 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 {
9242         // TODO: optimize
9243         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9244         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9245         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9246         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9247         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249         GL_Color(r, g, b, a);
9250         RSurf_DrawBatch();
9251 }
9252
9253 static void RSurf_DrawBatch_GL11_ClampColor(void)
9254 {
9255         int i;
9256         const float *c1;
9257         float *c2;
9258         if (!rsurface.passcolor4f)
9259                 return;
9260         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9261         {
9262                 c2[0] = bound(0.0f, c1[0], 1.0f);
9263                 c2[1] = bound(0.0f, c1[1], 1.0f);
9264                 c2[2] = bound(0.0f, c1[2], 1.0f);
9265                 c2[3] = bound(0.0f, c1[3], 1.0f);
9266         }
9267 }
9268
9269 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9270 {
9271         int i;
9272         float f;
9273         const float *v;
9274         const float *n;
9275         float *c;
9276         //vec3_t eyedir;
9277
9278         // fake shading
9279         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9280         rsurface.passcolor4f_vertexbuffer = 0;
9281         rsurface.passcolor4f_bufferoffset = 0;
9282         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9283         {
9284                 f = -DotProduct(r_refdef.view.forward, n);
9285                 f = max(0, f);
9286                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9287                 f *= r_refdef.lightmapintensity;
9288                 Vector4Set(c, f, f, f, 1);
9289         }
9290 }
9291
9292 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9293 {
9294         RSurf_DrawBatch_GL11_ApplyFakeLight();
9295         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9296         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9297         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9298         GL_Color(r, g, b, a);
9299         RSurf_DrawBatch();
9300 }
9301
9302 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9303 {
9304         int i;
9305         float f;
9306         float alpha;
9307         const float *v;
9308         const float *n;
9309         float *c;
9310         vec3_t ambientcolor;
9311         vec3_t diffusecolor;
9312         vec3_t lightdir;
9313         // TODO: optimize
9314         // model lighting
9315         VectorCopy(rsurface.modellight_lightdir, lightdir);
9316         f = 0.5f * r_refdef.lightmapintensity;
9317         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9318         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9319         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9320         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9321         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9322         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9323         alpha = *a;
9324         if (VectorLength2(diffusecolor) > 0)
9325         {
9326                 // q3-style directional shading
9327                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328                 rsurface.passcolor4f_vertexbuffer = 0;
9329                 rsurface.passcolor4f_bufferoffset = 0;
9330                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9331                 {
9332                         if ((f = DotProduct(n, lightdir)) > 0)
9333                                 VectorMA(ambientcolor, f, diffusecolor, c);
9334                         else
9335                                 VectorCopy(ambientcolor, c);
9336                         c[3] = alpha;
9337                 }
9338                 *r = 1;
9339                 *g = 1;
9340                 *b = 1;
9341                 *a = 1;
9342                 *applycolor = false;
9343         }
9344         else
9345         {
9346                 *r = ambientcolor[0];
9347                 *g = ambientcolor[1];
9348                 *b = ambientcolor[2];
9349                 rsurface.passcolor4f = NULL;
9350                 rsurface.passcolor4f_vertexbuffer = 0;
9351                 rsurface.passcolor4f_bufferoffset = 0;
9352         }
9353 }
9354
9355 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9356 {
9357         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9358         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9359         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9360         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9361         GL_Color(r, g, b, a);
9362         RSurf_DrawBatch();
9363 }
9364
9365 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9366 {
9367         int i;
9368         float f;
9369         const float *v;
9370         float *c;
9371
9372         // fake shading
9373         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374         rsurface.passcolor4f_vertexbuffer = 0;
9375         rsurface.passcolor4f_bufferoffset = 0;
9376
9377         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9378         {
9379                 f = 1 - RSurf_FogVertex(v);
9380                 c[0] = r;
9381                 c[1] = g;
9382                 c[2] = b;
9383                 c[3] = f * a;
9384         }
9385 }
9386
9387 void RSurf_SetupDepthAndCulling(void)
9388 {
9389         // submodels are biased to avoid z-fighting with world surfaces that they
9390         // may be exactly overlapping (avoids z-fighting artifacts on certain
9391         // doors and things in Quake maps)
9392         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9393         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9394         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9395         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9396 }
9397
9398 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9399 {
9400         // transparent sky would be ridiculous
9401         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9402                 return;
9403         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9404         skyrenderlater = true;
9405         RSurf_SetupDepthAndCulling();
9406         GL_DepthMask(true);
9407         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9408         // skymasking on them, and Quake3 never did sky masking (unlike
9409         // software Quake and software Quake2), so disable the sky masking
9410         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9411         // and skymasking also looks very bad when noclipping outside the
9412         // level, so don't use it then either.
9413         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9414         {
9415                 R_Mesh_ResetTextureState();
9416                 if (skyrendermasked)
9417                 {
9418                         R_SetupShader_DepthOrShadow();
9419                         // depth-only (masking)
9420                         GL_ColorMask(0,0,0,0);
9421                         // just to make sure that braindead drivers don't draw
9422                         // anything despite that colormask...
9423                         GL_BlendFunc(GL_ZERO, GL_ONE);
9424                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425                         if (rsurface.batchvertex3fbuffer)
9426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9427                         else
9428                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9429                 }
9430                 else
9431                 {
9432                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9433                         // fog sky
9434                         GL_BlendFunc(GL_ONE, GL_ZERO);
9435                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9437                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9438                 }
9439                 RSurf_DrawBatch();
9440                 if (skyrendermasked)
9441                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9442         }
9443         R_Mesh_ResetTextureState();
9444         GL_Color(1, 1, 1, 1);
9445 }
9446
9447 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9448 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9449 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9450 {
9451         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9452                 return;
9453         if (prepass)
9454         {
9455                 // render screenspace normalmap to texture
9456                 GL_DepthMask(true);
9457                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9458                 RSurf_DrawBatch();
9459                 return;
9460         }
9461
9462         // bind lightmap texture
9463
9464         // water/refraction/reflection/camera surfaces have to be handled specially
9465         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9466         {
9467                 int start, end, startplaneindex;
9468                 for (start = 0;start < texturenumsurfaces;start = end)
9469                 {
9470                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9471                         if(startplaneindex < 0)
9472                         {
9473                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9474                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9475                                 end = start + 1;
9476                                 continue;
9477                         }
9478                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9479                                 ;
9480                         // now that we have a batch using the same planeindex, render it
9481                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9482                         {
9483                                 // render water or distortion background
9484                                 GL_DepthMask(true);
9485                                 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));
9486                                 RSurf_DrawBatch();
9487                                 // blend surface on top
9488                                 GL_DepthMask(false);
9489                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9490                                 RSurf_DrawBatch();
9491                         }
9492                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9493                         {
9494                                 // render surface with reflection texture as input
9495                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9496                                 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));
9497                                 RSurf_DrawBatch();
9498                         }
9499                 }
9500                 return;
9501         }
9502
9503         // render surface batch normally
9504         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9505         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9506         RSurf_DrawBatch();
9507 }
9508
9509 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9510 {
9511         // OpenGL 1.3 path - anything not completely ancient
9512         qboolean applycolor;
9513         qboolean applyfog;
9514         int layerindex;
9515         const texturelayer_t *layer;
9516         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);
9517         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9518
9519         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9520         {
9521                 vec4_t layercolor;
9522                 int layertexrgbscale;
9523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9524                 {
9525                         if (layerindex == 0)
9526                                 GL_AlphaTest(true);
9527                         else
9528                         {
9529                                 GL_AlphaTest(false);
9530                                 GL_DepthFunc(GL_EQUAL);
9531                         }
9532                 }
9533                 GL_DepthMask(layer->depthmask && writedepth);
9534                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9535                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9536                 {
9537                         layertexrgbscale = 4;
9538                         VectorScale(layer->color, 0.25f, layercolor);
9539                 }
9540                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9541                 {
9542                         layertexrgbscale = 2;
9543                         VectorScale(layer->color, 0.5f, layercolor);
9544                 }
9545                 else
9546                 {
9547                         layertexrgbscale = 1;
9548                         VectorScale(layer->color, 1.0f, layercolor);
9549                 }
9550                 layercolor[3] = layer->color[3];
9551                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9552                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9553                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9554                 switch (layer->type)
9555                 {
9556                 case TEXTURELAYERTYPE_LITTEXTURE:
9557                         // single-pass lightmapped texture with 2x rgbscale
9558                         R_Mesh_TexBind(0, r_texture_white);
9559                         R_Mesh_TexMatrix(0, NULL);
9560                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9561                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9562                         R_Mesh_TexBind(1, layer->texture);
9563                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9564                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9565                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9566                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9567                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9568                         else if (FAKELIGHT_ENABLED)
9569                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9570                         else if (rsurface.uselightmaptexture)
9571                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9572                         else
9573                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9574                         break;
9575                 case TEXTURELAYERTYPE_TEXTURE:
9576                         // singletexture unlit texture with transparency support
9577                         R_Mesh_TexBind(0, layer->texture);
9578                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9579                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9580                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9581                         R_Mesh_TexBind(1, 0);
9582                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9583                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9584                         break;
9585                 case TEXTURELAYERTYPE_FOG:
9586                         // singletexture fogging
9587                         if (layer->texture)
9588                         {
9589                                 R_Mesh_TexBind(0, layer->texture);
9590                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9591                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9592                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9593                         }
9594                         else
9595                         {
9596                                 R_Mesh_TexBind(0, 0);
9597                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9598                         }
9599                         R_Mesh_TexBind(1, 0);
9600                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9601                         // generate a color array for the fog pass
9602                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9603                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9604                         RSurf_DrawBatch();
9605                         break;
9606                 default:
9607                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9608                 }
9609         }
9610         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9611         {
9612                 GL_DepthFunc(GL_LEQUAL);
9613                 GL_AlphaTest(false);
9614         }
9615 }
9616
9617 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9618 {
9619         // OpenGL 1.1 - crusty old voodoo path
9620         qboolean applyfog;
9621         int layerindex;
9622         const texturelayer_t *layer;
9623         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);
9624         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9625
9626         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9627         {
9628                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9629                 {
9630                         if (layerindex == 0)
9631                                 GL_AlphaTest(true);
9632                         else
9633                         {
9634                                 GL_AlphaTest(false);
9635                                 GL_DepthFunc(GL_EQUAL);
9636                         }
9637                 }
9638                 GL_DepthMask(layer->depthmask && writedepth);
9639                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9640                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9641                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9642                 switch (layer->type)
9643                 {
9644                 case TEXTURELAYERTYPE_LITTEXTURE:
9645                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9646                         {
9647                                 // two-pass lit texture with 2x rgbscale
9648                                 // first the lightmap pass
9649                                 R_Mesh_TexBind(0, r_texture_white);
9650                                 R_Mesh_TexMatrix(0, NULL);
9651                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9652                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9653                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9654                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9655                                 else if (FAKELIGHT_ENABLED)
9656                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9657                                 else if (rsurface.uselightmaptexture)
9658                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9659                                 else
9660                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9661                                 // then apply the texture to it
9662                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9663                                 R_Mesh_TexBind(0, layer->texture);
9664                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9665                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9666                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9667                                 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);
9668                         }
9669                         else
9670                         {
9671                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9672                                 R_Mesh_TexBind(0, layer->texture);
9673                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9674                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9675                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9676                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9677                                         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);
9678                                 else
9679                                         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);
9680                         }
9681                         break;
9682                 case TEXTURELAYERTYPE_TEXTURE:
9683                         // singletexture unlit texture with transparency support
9684                         R_Mesh_TexBind(0, layer->texture);
9685                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9686                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9687                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9688                         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);
9689                         break;
9690                 case TEXTURELAYERTYPE_FOG:
9691                         // singletexture fogging
9692                         if (layer->texture)
9693                         {
9694                                 R_Mesh_TexBind(0, layer->texture);
9695                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9696                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9697                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9698                         }
9699                         else
9700                         {
9701                                 R_Mesh_TexBind(0, 0);
9702                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9703                         }
9704                         // generate a color array for the fog pass
9705                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9706                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9707                         RSurf_DrawBatch();
9708                         break;
9709                 default:
9710                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9711                 }
9712         }
9713         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9714         {
9715                 GL_DepthFunc(GL_LEQUAL);
9716                 GL_AlphaTest(false);
9717         }
9718 }
9719
9720 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9721 {
9722         int vi;
9723         int j;
9724         r_vertexgeneric_t *batchvertex;
9725         float c[4];
9726
9727 //      R_Mesh_ResetTextureState();
9728         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9729
9730         if(rsurface.texture && rsurface.texture->currentskinframe)
9731         {
9732                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9733                 c[3] *= rsurface.texture->currentalpha;
9734         }
9735         else
9736         {
9737                 c[0] = 1;
9738                 c[1] = 0;
9739                 c[2] = 1;
9740                 c[3] = 1;
9741         }
9742
9743         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9744         {
9745                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9746                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9747                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9748         }
9749
9750         // brighten it up (as texture value 127 means "unlit")
9751         c[0] *= 2 * r_refdef.view.colorscale;
9752         c[1] *= 2 * r_refdef.view.colorscale;
9753         c[2] *= 2 * r_refdef.view.colorscale;
9754
9755         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9756                 c[3] *= r_wateralpha.value;
9757
9758         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9759         {
9760                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9761                 GL_DepthMask(false);
9762         }
9763         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9764         {
9765                 GL_BlendFunc(GL_ONE, GL_ONE);
9766                 GL_DepthMask(false);
9767         }
9768         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9769         {
9770                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9771                 GL_DepthMask(false);
9772         }
9773         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9774         {
9775                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9776                 GL_DepthMask(false);
9777         }
9778         else
9779         {
9780                 GL_BlendFunc(GL_ONE, GL_ZERO);
9781                 GL_DepthMask(writedepth);
9782         }
9783
9784         if (r_showsurfaces.integer == 3)
9785         {
9786                 rsurface.passcolor4f = NULL;
9787
9788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9789                 {
9790                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9791
9792                         rsurface.passcolor4f = NULL;
9793                         rsurface.passcolor4f_vertexbuffer = 0;
9794                         rsurface.passcolor4f_bufferoffset = 0;
9795                 }
9796                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9797                 {
9798                         qboolean applycolor = true;
9799                         float one = 1.0;
9800
9801                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9802
9803                         r_refdef.lightmapintensity = 1;
9804                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9805                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9806                 }
9807                 else if (FAKELIGHT_ENABLED)
9808                 {
9809                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9810
9811                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9812                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9813                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9814                 }
9815                 else
9816                 {
9817                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9818
9819                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9820                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9821                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9822                 }
9823
9824                 if(!rsurface.passcolor4f)
9825                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9826
9827                 RSurf_DrawBatch_GL11_ApplyAmbient();
9828                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9829                 if(r_refdef.fogenabled)
9830                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9831                 RSurf_DrawBatch_GL11_ClampColor();
9832
9833                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9834                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9835                 RSurf_DrawBatch();
9836         }
9837         else if (!r_refdef.view.showdebug)
9838         {
9839                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9840                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9841                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9842                 {
9843                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9844                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9845                 }
9846                 R_Mesh_PrepareVertices_Generic_Unlock();
9847                 RSurf_DrawBatch();
9848         }
9849         else if (r_showsurfaces.integer == 4)
9850         {
9851                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9852                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9853                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9854                 {
9855                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9856                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9857                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9858                 }
9859                 R_Mesh_PrepareVertices_Generic_Unlock();
9860                 RSurf_DrawBatch();
9861         }
9862         else if (r_showsurfaces.integer == 2)
9863         {
9864                 const int *e;
9865                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9866                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9867                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9868                 {
9869                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9870                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9871                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9872                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9873                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9874                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9875                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9876                 }
9877                 R_Mesh_PrepareVertices_Generic_Unlock();
9878                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9879         }
9880         else
9881         {
9882                 int texturesurfaceindex;
9883                 int k;
9884                 const msurface_t *surface;
9885                 float surfacecolor4f[4];
9886                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9887                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9888                 vi = 0;
9889                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9890                 {
9891                         surface = texturesurfacelist[texturesurfaceindex];
9892                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9893                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9894                         for (j = 0;j < surface->num_vertices;j++)
9895                         {
9896                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9897                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9898                                 vi++;
9899                         }
9900                 }
9901                 R_Mesh_PrepareVertices_Generic_Unlock();
9902                 RSurf_DrawBatch();
9903         }
9904 }
9905
9906 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9907 {
9908         CHECKGLERROR
9909         RSurf_SetupDepthAndCulling();
9910         if (r_showsurfaces.integer)
9911         {
9912                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9913                 return;
9914         }
9915         switch (vid.renderpath)
9916         {
9917         case RENDERPATH_GL20:
9918         case RENDERPATH_D3D9:
9919         case RENDERPATH_D3D10:
9920         case RENDERPATH_D3D11:
9921         case RENDERPATH_SOFT:
9922         case RENDERPATH_GLES2:
9923                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9924                 break;
9925         case RENDERPATH_GL13:
9926         case RENDERPATH_GLES1:
9927                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9928                 break;
9929         case RENDERPATH_GL11:
9930                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9931                 break;
9932         }
9933         CHECKGLERROR
9934 }
9935
9936 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9937 {
9938         CHECKGLERROR
9939         RSurf_SetupDepthAndCulling();
9940         if (r_showsurfaces.integer)
9941         {
9942                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9943                 return;
9944         }
9945         switch (vid.renderpath)
9946         {
9947         case RENDERPATH_GL20:
9948         case RENDERPATH_D3D9:
9949         case RENDERPATH_D3D10:
9950         case RENDERPATH_D3D11:
9951         case RENDERPATH_SOFT:
9952         case RENDERPATH_GLES2:
9953                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9954                 break;
9955         case RENDERPATH_GL13:
9956         case RENDERPATH_GLES1:
9957                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9958                 break;
9959         case RENDERPATH_GL11:
9960                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9961                 break;
9962         }
9963         CHECKGLERROR
9964 }
9965
9966 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9967 {
9968         int i, j;
9969         int texturenumsurfaces, endsurface;
9970         texture_t *texture;
9971         const msurface_t *surface;
9972         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9973
9974         // if the model is static it doesn't matter what value we give for
9975         // wantnormals and wanttangents, so this logic uses only rules applicable
9976         // to a model, knowing that they are meaningless otherwise
9977         if (ent == r_refdef.scene.worldentity)
9978                 RSurf_ActiveWorldEntity();
9979         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9980                 RSurf_ActiveModelEntity(ent, false, false, false);
9981         else
9982         {
9983                 switch (vid.renderpath)
9984                 {
9985                 case RENDERPATH_GL20:
9986                 case RENDERPATH_D3D9:
9987                 case RENDERPATH_D3D10:
9988                 case RENDERPATH_D3D11:
9989                 case RENDERPATH_SOFT:
9990                 case RENDERPATH_GLES2:
9991                         RSurf_ActiveModelEntity(ent, true, true, false);
9992                         break;
9993                 case RENDERPATH_GL11:
9994                 case RENDERPATH_GL13:
9995                 case RENDERPATH_GLES1:
9996                         RSurf_ActiveModelEntity(ent, true, false, false);
9997                         break;
9998                 }
9999         }
10000
10001         if (r_transparentdepthmasking.integer)
10002         {
10003                 qboolean setup = false;
10004                 for (i = 0;i < numsurfaces;i = j)
10005                 {
10006                         j = i + 1;
10007                         surface = rsurface.modelsurfaces + surfacelist[i];
10008                         texture = surface->texture;
10009                         rsurface.texture = R_GetCurrentTexture(texture);
10010                         rsurface.lightmaptexture = NULL;
10011                         rsurface.deluxemaptexture = NULL;
10012                         rsurface.uselightmaptexture = false;
10013                         // scan ahead until we find a different texture
10014                         endsurface = min(i + 1024, numsurfaces);
10015                         texturenumsurfaces = 0;
10016                         texturesurfacelist[texturenumsurfaces++] = surface;
10017                         for (;j < endsurface;j++)
10018                         {
10019                                 surface = rsurface.modelsurfaces + surfacelist[j];
10020                                 if (texture != surface->texture)
10021                                         break;
10022                                 texturesurfacelist[texturenumsurfaces++] = surface;
10023                         }
10024                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10025                                 continue;
10026                         // render the range of surfaces as depth
10027                         if (!setup)
10028                         {
10029                                 setup = true;
10030                                 GL_ColorMask(0,0,0,0);
10031                                 GL_Color(1,1,1,1);
10032                                 GL_DepthTest(true);
10033                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10034                                 GL_DepthMask(true);
10035 //                              R_Mesh_ResetTextureState();
10036                                 R_SetupShader_DepthOrShadow();
10037                         }
10038                         RSurf_SetupDepthAndCulling();
10039                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10040                         if (rsurface.batchvertex3fbuffer)
10041                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10042                         else
10043                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10044                         RSurf_DrawBatch();
10045                 }
10046                 if (setup)
10047                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10048         }
10049
10050         for (i = 0;i < numsurfaces;i = j)
10051         {
10052                 j = i + 1;
10053                 surface = rsurface.modelsurfaces + surfacelist[i];
10054                 texture = surface->texture;
10055                 rsurface.texture = R_GetCurrentTexture(texture);
10056                 // scan ahead until we find a different texture
10057                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10058                 texturenumsurfaces = 0;
10059                 texturesurfacelist[texturenumsurfaces++] = surface;
10060                 if(FAKELIGHT_ENABLED)
10061                 {
10062                         rsurface.lightmaptexture = NULL;
10063                         rsurface.deluxemaptexture = NULL;
10064                         rsurface.uselightmaptexture = false;
10065                         for (;j < endsurface;j++)
10066                         {
10067                                 surface = rsurface.modelsurfaces + surfacelist[j];
10068                                 if (texture != surface->texture)
10069                                         break;
10070                                 texturesurfacelist[texturenumsurfaces++] = surface;
10071                         }
10072                 }
10073                 else
10074                 {
10075                         rsurface.lightmaptexture = surface->lightmaptexture;
10076                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10077                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10078                         for (;j < endsurface;j++)
10079                         {
10080                                 surface = rsurface.modelsurfaces + surfacelist[j];
10081                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10082                                         break;
10083                                 texturesurfacelist[texturenumsurfaces++] = surface;
10084                         }
10085                 }
10086                 // render the range of surfaces
10087                 if (ent == r_refdef.scene.worldentity)
10088                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10089                 else
10090                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10091         }
10092         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10093 }
10094
10095 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10096 {
10097         // transparent surfaces get pushed off into the transparent queue
10098         int surfacelistindex;
10099         const msurface_t *surface;
10100         vec3_t tempcenter, center;
10101         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10102         {
10103                 surface = texturesurfacelist[surfacelistindex];
10104                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10105                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10106                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10107                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10108                 if (queueentity->transparent_offset) // transparent offset
10109                 {
10110                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10111                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10112                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10113                 }
10114                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10115         }
10116 }
10117
10118 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10119 {
10120         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10121                 return;
10122         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10123                 return;
10124         RSurf_SetupDepthAndCulling();
10125         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10126         if (rsurface.batchvertex3fbuffer)
10127                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10128         else
10129                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10130         RSurf_DrawBatch();
10131 }
10132
10133 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10134 {
10135         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10136         CHECKGLERROR
10137         if (depthonly)
10138                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10139         else if (prepass)
10140         {
10141                 if (!rsurface.texture->currentnumlayers)
10142                         return;
10143                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10144                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10145                 else
10146                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10147         }
10148         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10149                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10150         else if (!rsurface.texture->currentnumlayers)
10151                 return;
10152         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10153         {
10154                 // in the deferred case, transparent surfaces were queued during prepass
10155                 if (!r_shadow_usingdeferredprepass)
10156                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10157         }
10158         else
10159         {
10160                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10161                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10162         }
10163         CHECKGLERROR
10164 }
10165
10166 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10167 {
10168         int i, j;
10169         texture_t *texture;
10170         R_FrameData_SetMark();
10171         // break the surface list down into batches by texture and use of lightmapping
10172         for (i = 0;i < numsurfaces;i = j)
10173         {
10174                 j = i + 1;
10175                 // texture is the base texture pointer, rsurface.texture is the
10176                 // current frame/skin the texture is directing us to use (for example
10177                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10178                 // use skin 1 instead)
10179                 texture = surfacelist[i]->texture;
10180                 rsurface.texture = R_GetCurrentTexture(texture);
10181                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10182                 {
10183                         // if this texture is not the kind we want, skip ahead to the next one
10184                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10185                                 ;
10186                         continue;
10187                 }
10188                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10189                 {
10190                         rsurface.lightmaptexture = NULL;
10191                         rsurface.deluxemaptexture = NULL;
10192                         rsurface.uselightmaptexture = false;
10193                         // simply scan ahead until we find a different texture or lightmap state
10194                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10195                                 ;
10196                 }
10197                 else
10198                 {
10199                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10200                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10201                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10202                         // simply scan ahead until we find a different texture or lightmap state
10203                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10204                                 ;
10205                 }
10206                 // render the range of surfaces
10207                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10208         }
10209         R_FrameData_ReturnToMark();
10210 }
10211
10212 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10213 {
10214         CHECKGLERROR
10215         if (depthonly)
10216                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10217         else if (prepass)
10218         {
10219                 if (!rsurface.texture->currentnumlayers)
10220                         return;
10221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10222                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10223                 else
10224                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10225         }
10226         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10227                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10228         else if (!rsurface.texture->currentnumlayers)
10229                 return;
10230         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10231         {
10232                 // in the deferred case, transparent surfaces were queued during prepass
10233                 if (!r_shadow_usingdeferredprepass)
10234                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10235         }
10236         else
10237         {
10238                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10239                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10240         }
10241         CHECKGLERROR
10242 }
10243
10244 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10245 {
10246         int i, j;
10247         texture_t *texture;
10248         R_FrameData_SetMark();
10249         // break the surface list down into batches by texture and use of lightmapping
10250         for (i = 0;i < numsurfaces;i = j)
10251         {
10252                 j = i + 1;
10253                 // texture is the base texture pointer, rsurface.texture is the
10254                 // current frame/skin the texture is directing us to use (for example
10255                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10256                 // use skin 1 instead)
10257                 texture = surfacelist[i]->texture;
10258                 rsurface.texture = R_GetCurrentTexture(texture);
10259                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10260                 {
10261                         // if this texture is not the kind we want, skip ahead to the next one
10262                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10263                                 ;
10264                         continue;
10265                 }
10266                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10267                 {
10268                         rsurface.lightmaptexture = NULL;
10269                         rsurface.deluxemaptexture = NULL;
10270                         rsurface.uselightmaptexture = false;
10271                         // simply scan ahead until we find a different texture or lightmap state
10272                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10273                                 ;
10274                 }
10275                 else
10276                 {
10277                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10278                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10279                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10280                         // simply scan ahead until we find a different texture or lightmap state
10281                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10282                                 ;
10283                 }
10284                 // render the range of surfaces
10285                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10286         }
10287         R_FrameData_ReturnToMark();
10288 }
10289
10290 float locboxvertex3f[6*4*3] =
10291 {
10292         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10293         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10294         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10295         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10296         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10297         1,0,0, 0,0,0, 0,1,0, 1,1,0
10298 };
10299
10300 unsigned short locboxelements[6*2*3] =
10301 {
10302          0, 1, 2, 0, 2, 3,
10303          4, 5, 6, 4, 6, 7,
10304          8, 9,10, 8,10,11,
10305         12,13,14, 12,14,15,
10306         16,17,18, 16,18,19,
10307         20,21,22, 20,22,23
10308 };
10309
10310 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10311 {
10312         int i, j;
10313         cl_locnode_t *loc = (cl_locnode_t *)ent;
10314         vec3_t mins, size;
10315         float vertex3f[6*4*3];
10316         CHECKGLERROR
10317         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10318         GL_DepthMask(false);
10319         GL_DepthRange(0, 1);
10320         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10321         GL_DepthTest(true);
10322         GL_CullFace(GL_NONE);
10323         R_EntityMatrix(&identitymatrix);
10324
10325 //      R_Mesh_ResetTextureState();
10326
10327         i = surfacelist[0];
10328         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10329                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10330                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10331                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10332
10333         if (VectorCompare(loc->mins, loc->maxs))
10334         {
10335                 VectorSet(size, 2, 2, 2);
10336                 VectorMA(loc->mins, -0.5f, size, mins);
10337         }
10338         else
10339         {
10340                 VectorCopy(loc->mins, mins);
10341                 VectorSubtract(loc->maxs, loc->mins, size);
10342         }
10343
10344         for (i = 0;i < 6*4*3;)
10345                 for (j = 0;j < 3;j++, i++)
10346                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10347
10348         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10349         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10350         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10351 }
10352
10353 void R_DrawLocs(void)
10354 {
10355         int index;
10356         cl_locnode_t *loc, *nearestloc;
10357         vec3_t center;
10358         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10359         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10360         {
10361                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10362                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10363         }
10364 }
10365
10366 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10367 {
10368         if (decalsystem->decals)
10369                 Mem_Free(decalsystem->decals);
10370         memset(decalsystem, 0, sizeof(*decalsystem));
10371 }
10372
10373 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)
10374 {
10375         tridecal_t *decal;
10376         tridecal_t *decals;
10377         int i;
10378
10379         // expand or initialize the system
10380         if (decalsystem->maxdecals <= decalsystem->numdecals)
10381         {
10382                 decalsystem_t old = *decalsystem;
10383                 qboolean useshortelements;
10384                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10385                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10386                 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)));
10387                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10388                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10389                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10390                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10391                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10392                 if (decalsystem->numdecals)
10393                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10394                 if (old.decals)
10395                         Mem_Free(old.decals);
10396                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10397                         decalsystem->element3i[i] = i;
10398                 if (useshortelements)
10399                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10400                                 decalsystem->element3s[i] = i;
10401         }
10402
10403         // grab a decal and search for another free slot for the next one
10404         decals = decalsystem->decals;
10405         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10406         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10407                 ;
10408         decalsystem->freedecal = i;
10409         if (decalsystem->numdecals <= i)
10410                 decalsystem->numdecals = i + 1;
10411
10412         // initialize the decal
10413         decal->lived = 0;
10414         decal->triangleindex = triangleindex;
10415         decal->surfaceindex = surfaceindex;
10416         decal->decalsequence = decalsequence;
10417         decal->color4f[0][0] = c0[0];
10418         decal->color4f[0][1] = c0[1];
10419         decal->color4f[0][2] = c0[2];
10420         decal->color4f[0][3] = 1;
10421         decal->color4f[1][0] = c1[0];
10422         decal->color4f[1][1] = c1[1];
10423         decal->color4f[1][2] = c1[2];
10424         decal->color4f[1][3] = 1;
10425         decal->color4f[2][0] = c2[0];
10426         decal->color4f[2][1] = c2[1];
10427         decal->color4f[2][2] = c2[2];
10428         decal->color4f[2][3] = 1;
10429         decal->vertex3f[0][0] = v0[0];
10430         decal->vertex3f[0][1] = v0[1];
10431         decal->vertex3f[0][2] = v0[2];
10432         decal->vertex3f[1][0] = v1[0];
10433         decal->vertex3f[1][1] = v1[1];
10434         decal->vertex3f[1][2] = v1[2];
10435         decal->vertex3f[2][0] = v2[0];
10436         decal->vertex3f[2][1] = v2[1];
10437         decal->vertex3f[2][2] = v2[2];
10438         decal->texcoord2f[0][0] = t0[0];
10439         decal->texcoord2f[0][1] = t0[1];
10440         decal->texcoord2f[1][0] = t1[0];
10441         decal->texcoord2f[1][1] = t1[1];
10442         decal->texcoord2f[2][0] = t2[0];
10443         decal->texcoord2f[2][1] = t2[1];
10444         TriangleNormal(v0, v1, v2, decal->plane);
10445         VectorNormalize(decal->plane);
10446         decal->plane[3] = DotProduct(v0, decal->plane);
10447 }
10448
10449 extern cvar_t cl_decals_bias;
10450 extern cvar_t cl_decals_models;
10451 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10452 // baseparms, parms, temps
10453 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)
10454 {
10455         int cornerindex;
10456         int index;
10457         float v[9][3];
10458         const float *vertex3f;
10459         const float *normal3f;
10460         int numpoints;
10461         float points[2][9][3];
10462         float temp[3];
10463         float tc[9][2];
10464         float f;
10465         float c[9][4];
10466         const int *e;
10467
10468         e = rsurface.modelelement3i + 3*triangleindex;
10469
10470         vertex3f = rsurface.modelvertex3f;
10471         normal3f = rsurface.modelnormal3f;
10472
10473         if (normal3f)
10474         {
10475                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10476                 {
10477                         index = 3*e[cornerindex];
10478                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10479                 }
10480         }
10481         else
10482         {
10483                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10484                 {
10485                         index = 3*e[cornerindex];
10486                         VectorCopy(vertex3f + index, v[cornerindex]);
10487                 }
10488         }
10489
10490         // cull backfaces
10491         //TriangleNormal(v[0], v[1], v[2], normal);
10492         //if (DotProduct(normal, localnormal) < 0.0f)
10493         //      continue;
10494         // clip by each of the box planes formed from the projection matrix
10495         // if anything survives, we emit the decal
10496         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]);
10497         if (numpoints < 3)
10498                 return;
10499         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]);
10500         if (numpoints < 3)
10501                 return;
10502         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]);
10503         if (numpoints < 3)
10504                 return;
10505         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]);
10506         if (numpoints < 3)
10507                 return;
10508         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]);
10509         if (numpoints < 3)
10510                 return;
10511         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]);
10512         if (numpoints < 3)
10513                 return;
10514         // some part of the triangle survived, so we have to accept it...
10515         if (dynamic)
10516         {
10517                 // dynamic always uses the original triangle
10518                 numpoints = 3;
10519                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10520                 {
10521                         index = 3*e[cornerindex];
10522                         VectorCopy(vertex3f + index, v[cornerindex]);
10523                 }
10524         }
10525         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10526         {
10527                 // convert vertex positions to texcoords
10528                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10529                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10530                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10531                 // calculate distance fade from the projection origin
10532                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10533                 f = bound(0.0f, f, 1.0f);
10534                 c[cornerindex][0] = r * f;
10535                 c[cornerindex][1] = g * f;
10536                 c[cornerindex][2] = b * f;
10537                 c[cornerindex][3] = 1.0f;
10538                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10539         }
10540         if (dynamic)
10541                 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);
10542         else
10543                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10544                         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);
10545 }
10546 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)
10547 {
10548         matrix4x4_t projection;
10549         decalsystem_t *decalsystem;
10550         qboolean dynamic;
10551         dp_model_t *model;
10552         const msurface_t *surface;
10553         const msurface_t *surfaces;
10554         const int *surfacelist;
10555         const texture_t *texture;
10556         int numtriangles;
10557         int numsurfacelist;
10558         int surfacelistindex;
10559         int surfaceindex;
10560         int triangleindex;
10561         float localorigin[3];
10562         float localnormal[3];
10563         float localmins[3];
10564         float localmaxs[3];
10565         float localsize;
10566         //float normal[3];
10567         float planes[6][4];
10568         float angles[3];
10569         bih_t *bih;
10570         int bih_triangles_count;
10571         int bih_triangles[256];
10572         int bih_surfaces[256];
10573
10574         decalsystem = &ent->decalsystem;
10575         model = ent->model;
10576         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10577         {
10578                 R_DecalSystem_Reset(&ent->decalsystem);
10579                 return;
10580         }
10581
10582         if (!model->brush.data_leafs && !cl_decals_models.integer)
10583         {
10584                 if (decalsystem->model)
10585                         R_DecalSystem_Reset(decalsystem);
10586                 return;
10587         }
10588
10589         if (decalsystem->model != model)
10590                 R_DecalSystem_Reset(decalsystem);
10591         decalsystem->model = model;
10592
10593         RSurf_ActiveModelEntity(ent, true, false, false);
10594
10595         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10596         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10597         VectorNormalize(localnormal);
10598         localsize = worldsize*rsurface.inversematrixscale;
10599         localmins[0] = localorigin[0] - localsize;
10600         localmins[1] = localorigin[1] - localsize;
10601         localmins[2] = localorigin[2] - localsize;
10602         localmaxs[0] = localorigin[0] + localsize;
10603         localmaxs[1] = localorigin[1] + localsize;
10604         localmaxs[2] = localorigin[2] + localsize;
10605
10606         //VectorCopy(localnormal, planes[4]);
10607         //VectorVectors(planes[4], planes[2], planes[0]);
10608         AnglesFromVectors(angles, localnormal, NULL, false);
10609         AngleVectors(angles, planes[0], planes[2], planes[4]);
10610         VectorNegate(planes[0], planes[1]);
10611         VectorNegate(planes[2], planes[3]);
10612         VectorNegate(planes[4], planes[5]);
10613         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10614         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10615         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10616         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10617         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10618         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10619
10620 #if 1
10621 // works
10622 {
10623         matrix4x4_t forwardprojection;
10624         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10625         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10626 }
10627 #else
10628 // broken
10629 {
10630         float projectionvector[4][3];
10631         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10632         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10633         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10634         projectionvector[0][0] = planes[0][0] * ilocalsize;
10635         projectionvector[0][1] = planes[1][0] * ilocalsize;
10636         projectionvector[0][2] = planes[2][0] * ilocalsize;
10637         projectionvector[1][0] = planes[0][1] * ilocalsize;
10638         projectionvector[1][1] = planes[1][1] * ilocalsize;
10639         projectionvector[1][2] = planes[2][1] * ilocalsize;
10640         projectionvector[2][0] = planes[0][2] * ilocalsize;
10641         projectionvector[2][1] = planes[1][2] * ilocalsize;
10642         projectionvector[2][2] = planes[2][2] * ilocalsize;
10643         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10644         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10645         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10646         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10647 }
10648 #endif
10649
10650         dynamic = model->surfmesh.isanimated;
10651         numsurfacelist = model->nummodelsurfaces;
10652         surfacelist = model->sortedmodelsurfaces;
10653         surfaces = model->data_surfaces;
10654
10655         bih = NULL;
10656         bih_triangles_count = -1;
10657         if(!dynamic)
10658         {
10659                 if(model->render_bih.numleafs)
10660                         bih = &model->render_bih;
10661                 else if(model->collision_bih.numleafs)
10662                         bih = &model->collision_bih;
10663         }
10664         if(bih)
10665                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10666         if(bih_triangles_count == 0)
10667                 return;
10668         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10669                 return;
10670         if(bih_triangles_count > 0)
10671         {
10672                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10673                 {
10674                         surfaceindex = bih_surfaces[triangleindex];
10675                         surface = surfaces + surfaceindex;
10676                         texture = surface->texture;
10677                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10678                                 continue;
10679                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10680                                 continue;
10681                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10682                 }
10683         }
10684         else
10685         {
10686                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10687                 {
10688                         surfaceindex = surfacelist[surfacelistindex];
10689                         surface = surfaces + surfaceindex;
10690                         // check cull box first because it rejects more than any other check
10691                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10692                                 continue;
10693                         // skip transparent surfaces
10694                         texture = surface->texture;
10695                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10696                                 continue;
10697                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10698                                 continue;
10699                         numtriangles = surface->num_triangles;
10700                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10701                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10702                 }
10703         }
10704 }
10705
10706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10707 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)
10708 {
10709         int renderentityindex;
10710         float worldmins[3];
10711         float worldmaxs[3];
10712         entity_render_t *ent;
10713
10714         if (!cl_decals_newsystem.integer)
10715                 return;
10716
10717         worldmins[0] = worldorigin[0] - worldsize;
10718         worldmins[1] = worldorigin[1] - worldsize;
10719         worldmins[2] = worldorigin[2] - worldsize;
10720         worldmaxs[0] = worldorigin[0] + worldsize;
10721         worldmaxs[1] = worldorigin[1] + worldsize;
10722         worldmaxs[2] = worldorigin[2] + worldsize;
10723
10724         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10725
10726         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10727         {
10728                 ent = r_refdef.scene.entities[renderentityindex];
10729                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10730                         continue;
10731
10732                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10733         }
10734 }
10735
10736 typedef struct r_decalsystem_splatqueue_s
10737 {
10738         vec3_t worldorigin;
10739         vec3_t worldnormal;
10740         float color[4];
10741         float tcrange[4];
10742         float worldsize;
10743         int decalsequence;
10744 }
10745 r_decalsystem_splatqueue_t;
10746
10747 int r_decalsystem_numqueued = 0;
10748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10749
10750 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)
10751 {
10752         r_decalsystem_splatqueue_t *queue;
10753
10754         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10755                 return;
10756
10757         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10758         VectorCopy(worldorigin, queue->worldorigin);
10759         VectorCopy(worldnormal, queue->worldnormal);
10760         Vector4Set(queue->color, r, g, b, a);
10761         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10762         queue->worldsize = worldsize;
10763         queue->decalsequence = cl.decalsequence++;
10764 }
10765
10766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10767 {
10768         int i;
10769         r_decalsystem_splatqueue_t *queue;
10770
10771         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10772                 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);
10773         r_decalsystem_numqueued = 0;
10774 }
10775
10776 extern cvar_t cl_decals_max;
10777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10778 {
10779         int i;
10780         decalsystem_t *decalsystem = &ent->decalsystem;
10781         int numdecals;
10782         int killsequence;
10783         tridecal_t *decal;
10784         float frametime;
10785         float lifetime;
10786
10787         if (!decalsystem->numdecals)
10788                 return;
10789
10790         if (r_showsurfaces.integer)
10791                 return;
10792
10793         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10794         {
10795                 R_DecalSystem_Reset(decalsystem);
10796                 return;
10797         }
10798
10799         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10800         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10801
10802         if (decalsystem->lastupdatetime)
10803                 frametime = (cl.time - decalsystem->lastupdatetime);
10804         else
10805                 frametime = 0;
10806         decalsystem->lastupdatetime = cl.time;
10807         decal = decalsystem->decals;
10808         numdecals = decalsystem->numdecals;
10809
10810         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10811         {
10812                 if (decal->color4f[0][3])
10813                 {
10814                         decal->lived += frametime;
10815                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10816                         {
10817                                 memset(decal, 0, sizeof(*decal));
10818                                 if (decalsystem->freedecal > i)
10819                                         decalsystem->freedecal = i;
10820                         }
10821                 }
10822         }
10823         decal = decalsystem->decals;
10824         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10825                 numdecals--;
10826
10827         // collapse the array by shuffling the tail decals into the gaps
10828         for (;;)
10829         {
10830                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10831                         decalsystem->freedecal++;
10832                 if (decalsystem->freedecal == numdecals)
10833                         break;
10834                 decal[decalsystem->freedecal] = decal[--numdecals];
10835         }
10836
10837         decalsystem->numdecals = numdecals;
10838
10839         if (numdecals <= 0)
10840         {
10841                 // if there are no decals left, reset decalsystem
10842                 R_DecalSystem_Reset(decalsystem);
10843         }
10844 }
10845
10846 extern skinframe_t *decalskinframe;
10847 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10848 {
10849         int i;
10850         decalsystem_t *decalsystem = &ent->decalsystem;
10851         int numdecals;
10852         tridecal_t *decal;
10853         float faderate;
10854         float alpha;
10855         float *v3f;
10856         float *c4f;
10857         float *t2f;
10858         const int *e;
10859         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10860         int numtris = 0;
10861
10862         numdecals = decalsystem->numdecals;
10863         if (!numdecals)
10864                 return;
10865
10866         if (r_showsurfaces.integer)
10867                 return;
10868
10869         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10870         {
10871                 R_DecalSystem_Reset(decalsystem);
10872                 return;
10873         }
10874
10875         // if the model is static it doesn't matter what value we give for
10876         // wantnormals and wanttangents, so this logic uses only rules applicable
10877         // to a model, knowing that they are meaningless otherwise
10878         if (ent == r_refdef.scene.worldentity)
10879                 RSurf_ActiveWorldEntity();
10880         else
10881                 RSurf_ActiveModelEntity(ent, false, false, false);
10882
10883         decalsystem->lastupdatetime = cl.time;
10884         decal = decalsystem->decals;
10885
10886         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10887
10888         // update vertex positions for animated models
10889         v3f = decalsystem->vertex3f;
10890         c4f = decalsystem->color4f;
10891         t2f = decalsystem->texcoord2f;
10892         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10893         {
10894                 if (!decal->color4f[0][3])
10895                         continue;
10896
10897                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10898                         continue;
10899
10900                 // skip backfaces
10901                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10902                         continue;
10903
10904                 // update color values for fading decals
10905                 if (decal->lived >= cl_decals_time.value)
10906                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10907                 else
10908                         alpha = 1.0f;
10909
10910                 c4f[ 0] = decal->color4f[0][0] * alpha;
10911                 c4f[ 1] = decal->color4f[0][1] * alpha;
10912                 c4f[ 2] = decal->color4f[0][2] * alpha;
10913                 c4f[ 3] = 1;
10914                 c4f[ 4] = decal->color4f[1][0] * alpha;
10915                 c4f[ 5] = decal->color4f[1][1] * alpha;
10916                 c4f[ 6] = decal->color4f[1][2] * alpha;
10917                 c4f[ 7] = 1;
10918                 c4f[ 8] = decal->color4f[2][0] * alpha;
10919                 c4f[ 9] = decal->color4f[2][1] * alpha;
10920                 c4f[10] = decal->color4f[2][2] * alpha;
10921                 c4f[11] = 1;
10922
10923                 t2f[0] = decal->texcoord2f[0][0];
10924                 t2f[1] = decal->texcoord2f[0][1];
10925                 t2f[2] = decal->texcoord2f[1][0];
10926                 t2f[3] = decal->texcoord2f[1][1];
10927                 t2f[4] = decal->texcoord2f[2][0];
10928                 t2f[5] = decal->texcoord2f[2][1];
10929
10930                 // update vertex positions for animated models
10931                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10932                 {
10933                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10934                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10935                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10936                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10937                 }
10938                 else
10939                 {
10940                         VectorCopy(decal->vertex3f[0], v3f);
10941                         VectorCopy(decal->vertex3f[1], v3f + 3);
10942                         VectorCopy(decal->vertex3f[2], v3f + 6);
10943                 }
10944
10945                 if (r_refdef.fogenabled)
10946                 {
10947                         alpha = RSurf_FogVertex(v3f);
10948                         VectorScale(c4f, alpha, c4f);
10949                         alpha = RSurf_FogVertex(v3f + 3);
10950                         VectorScale(c4f + 4, alpha, c4f + 4);
10951                         alpha = RSurf_FogVertex(v3f + 6);
10952                         VectorScale(c4f + 8, alpha, c4f + 8);
10953                 }
10954
10955                 v3f += 9;
10956                 c4f += 12;
10957                 t2f += 6;
10958                 numtris++;
10959         }
10960
10961         if (numtris > 0)
10962         {
10963                 r_refdef.stats.drawndecals += numtris;
10964
10965                 // now render the decals all at once
10966                 // (this assumes they all use one particle font texture!)
10967                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10968 //              R_Mesh_ResetTextureState();
10969                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10970                 GL_DepthMask(false);
10971                 GL_DepthRange(0, 1);
10972                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10973                 GL_DepthTest(true);
10974                 GL_CullFace(GL_NONE);
10975                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10976                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10977                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10978         }
10979 }
10980
10981 static void R_DrawModelDecals(void)
10982 {
10983         int i, numdecals;
10984
10985         // fade faster when there are too many decals
10986         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10987         for (i = 0;i < r_refdef.scene.numentities;i++)
10988                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10989
10990         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10991         for (i = 0;i < r_refdef.scene.numentities;i++)
10992                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10993                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10994
10995         R_DecalSystem_ApplySplatEntitiesQueue();
10996
10997         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10998         for (i = 0;i < r_refdef.scene.numentities;i++)
10999                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11000
11001         r_refdef.stats.totaldecals += numdecals;
11002
11003         if (r_showsurfaces.integer)
11004                 return;
11005
11006         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11007
11008         for (i = 0;i < r_refdef.scene.numentities;i++)
11009         {
11010                 if (!r_refdef.viewcache.entityvisible[i])
11011                         continue;
11012                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11013                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11014         }
11015 }
11016
11017 extern cvar_t mod_collision_bih;
11018 void R_DrawDebugModel(void)
11019 {
11020         entity_render_t *ent = rsurface.entity;
11021         int i, j, k, l, flagsmask;
11022         const msurface_t *surface;
11023         dp_model_t *model = ent->model;
11024         vec3_t v;
11025
11026         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11027                 return;
11028
11029         if (r_showoverdraw.value > 0)
11030         {
11031                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11032                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11033                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11034                 GL_DepthTest(false);
11035                 GL_DepthMask(false);
11036                 GL_DepthRange(0, 1);
11037                 GL_BlendFunc(GL_ONE, GL_ONE);
11038                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11039                 {
11040                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11041                                 continue;
11042                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11043                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11044                         {
11045                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11046                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11047                                 if (!rsurface.texture->currentlayers->depthmask)
11048                                         GL_Color(c, 0, 0, 1.0f);
11049                                 else if (ent == r_refdef.scene.worldentity)
11050                                         GL_Color(c, c, c, 1.0f);
11051                                 else
11052                                         GL_Color(0, c, 0, 1.0f);
11053                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11054                                 RSurf_DrawBatch();
11055                         }
11056                 }
11057                 rsurface.texture = NULL;
11058         }
11059
11060         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11061
11062 //      R_Mesh_ResetTextureState();
11063         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11064         GL_DepthRange(0, 1);
11065         GL_DepthTest(!r_showdisabledepthtest.integer);
11066         GL_DepthMask(false);
11067         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11068
11069         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11070         {
11071                 int triangleindex;
11072                 int bihleafindex;
11073                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11074                 const q3mbrush_t *brush;
11075                 const bih_t *bih = &model->collision_bih;
11076                 const bih_leaf_t *bihleaf;
11077                 float vertex3f[3][3];
11078                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11079                 cullbox = false;
11080                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11081                 {
11082                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11083                                 continue;
11084                         switch (bihleaf->type)
11085                         {
11086                         case BIH_BRUSH:
11087                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11088                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11089                                 {
11090                                         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);
11091                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11092                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11093                                 }
11094                                 break;
11095                         case BIH_COLLISIONTRIANGLE:
11096                                 triangleindex = bihleaf->itemindex;
11097                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11098                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11099                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11100                                 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);
11101                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11102                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11103                                 break;
11104                         case BIH_RENDERTRIANGLE:
11105                                 triangleindex = bihleaf->itemindex;
11106                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11107                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11108                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11109                                 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);
11110                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11111                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11112                                 break;
11113                         }
11114                 }
11115         }
11116
11117         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11118
11119         if (r_showtris.integer && qglPolygonMode)
11120         {
11121                 if (r_showdisabledepthtest.integer)
11122                 {
11123                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11124                         GL_DepthMask(false);
11125                 }
11126                 else
11127                 {
11128                         GL_BlendFunc(GL_ONE, GL_ZERO);
11129                         GL_DepthMask(true);
11130                 }
11131                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11132                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11133                 {
11134                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11135                                 continue;
11136                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11137                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11138                         {
11139                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11140                                 if (!rsurface.texture->currentlayers->depthmask)
11141                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11142                                 else if (ent == r_refdef.scene.worldentity)
11143                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11144                                 else
11145                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11146                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11147                                 RSurf_DrawBatch();
11148                         }
11149                 }
11150                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11151                 rsurface.texture = NULL;
11152         }
11153
11154         if (r_shownormals.value != 0 && qglBegin)
11155         {
11156                 if (r_showdisabledepthtest.integer)
11157                 {
11158                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11159                         GL_DepthMask(false);
11160                 }
11161                 else
11162                 {
11163                         GL_BlendFunc(GL_ONE, GL_ZERO);
11164                         GL_DepthMask(true);
11165                 }
11166                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11167                 {
11168                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11169                                 continue;
11170                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11171                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11172                         {
11173                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11174                                 qglBegin(GL_LINES);
11175                                 if (r_shownormals.value < 0)
11176                                 {
11177                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11178                                         {
11179                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11180                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11181                                                 qglVertex3f(v[0], v[1], v[2]);
11182                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11183                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11184                                                 qglVertex3f(v[0], v[1], v[2]);
11185                                         }
11186                                 }
11187                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11188                                 {
11189                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11190                                         {
11191                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11192                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11193                                                 qglVertex3f(v[0], v[1], v[2]);
11194                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11195                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11196                                                 qglVertex3f(v[0], v[1], v[2]);
11197                                         }
11198                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11199                                         {
11200                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11201                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11202                                                 qglVertex3f(v[0], v[1], v[2]);
11203                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11204                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11205                                                 qglVertex3f(v[0], v[1], v[2]);
11206                                         }
11207                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11208                                         {
11209                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11210                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11211                                                 qglVertex3f(v[0], v[1], v[2]);
11212                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11213                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11214                                                 qglVertex3f(v[0], v[1], v[2]);
11215                                         }
11216                                 }
11217                                 qglEnd();
11218                                 CHECKGLERROR
11219                         }
11220                 }
11221                 rsurface.texture = NULL;
11222         }
11223 }
11224
11225 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11226 int r_maxsurfacelist = 0;
11227 const msurface_t **r_surfacelist = NULL;
11228 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11229 {
11230         int i, j, endj, flagsmask;
11231         dp_model_t *model = r_refdef.scene.worldmodel;
11232         msurface_t *surfaces;
11233         unsigned char *update;
11234         int numsurfacelist = 0;
11235         if (model == NULL)
11236                 return;
11237
11238         if (r_maxsurfacelist < model->num_surfaces)
11239         {
11240                 r_maxsurfacelist = model->num_surfaces;
11241                 if (r_surfacelist)
11242                         Mem_Free((msurface_t**)r_surfacelist);
11243                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11244         }
11245
11246         RSurf_ActiveWorldEntity();
11247
11248         surfaces = model->data_surfaces;
11249         update = model->brushq1.lightmapupdateflags;
11250
11251         // update light styles on this submodel
11252         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11253         {
11254                 model_brush_lightstyleinfo_t *style;
11255                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11256                 {
11257                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11258                         {
11259                                 int *list = style->surfacelist;
11260                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11261                                 for (j = 0;j < style->numsurfaces;j++)
11262                                         update[list[j]] = true;
11263                         }
11264                 }
11265         }
11266
11267         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11268
11269         if (debug)
11270         {
11271                 R_DrawDebugModel();
11272                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11273                 return;
11274         }
11275
11276         rsurface.lightmaptexture = NULL;
11277         rsurface.deluxemaptexture = NULL;
11278         rsurface.uselightmaptexture = false;
11279         rsurface.texture = NULL;
11280         rsurface.rtlight = NULL;
11281         numsurfacelist = 0;
11282         // add visible surfaces to draw list
11283         for (i = 0;i < model->nummodelsurfaces;i++)
11284         {
11285                 j = model->sortedmodelsurfaces[i];
11286                 if (r_refdef.viewcache.world_surfacevisible[j])
11287                         r_surfacelist[numsurfacelist++] = surfaces + j;
11288         }
11289         // update lightmaps if needed
11290         if (model->brushq1.firstrender)
11291         {
11292                 model->brushq1.firstrender = false;
11293                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11294                         if (update[j])
11295                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11296         }
11297         else if (update)
11298         {
11299                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11300                         if (r_refdef.viewcache.world_surfacevisible[j])
11301                                 if (update[j])
11302                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11303         }
11304         // don't do anything if there were no surfaces
11305         if (!numsurfacelist)
11306         {
11307                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11308                 return;
11309         }
11310         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11311
11312         // add to stats if desired
11313         if (r_speeds.integer && !skysurfaces && !depthonly)
11314         {
11315                 r_refdef.stats.world_surfaces += numsurfacelist;
11316                 for (j = 0;j < numsurfacelist;j++)
11317                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11318         }
11319
11320         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11321 }
11322
11323 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11324 {
11325         int i, j, endj, flagsmask;
11326         dp_model_t *model = ent->model;
11327         msurface_t *surfaces;
11328         unsigned char *update;
11329         int numsurfacelist = 0;
11330         if (model == NULL)
11331                 return;
11332
11333         if (r_maxsurfacelist < model->num_surfaces)
11334         {
11335                 r_maxsurfacelist = model->num_surfaces;
11336                 if (r_surfacelist)
11337                         Mem_Free((msurface_t **)r_surfacelist);
11338                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11339         }
11340
11341         // if the model is static it doesn't matter what value we give for
11342         // wantnormals and wanttangents, so this logic uses only rules applicable
11343         // to a model, knowing that they are meaningless otherwise
11344         if (ent == r_refdef.scene.worldentity)
11345                 RSurf_ActiveWorldEntity();
11346         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11347                 RSurf_ActiveModelEntity(ent, false, false, false);
11348         else if (prepass)
11349                 RSurf_ActiveModelEntity(ent, true, true, true);
11350         else if (depthonly)
11351         {
11352                 switch (vid.renderpath)
11353                 {
11354                 case RENDERPATH_GL20:
11355                 case RENDERPATH_D3D9:
11356                 case RENDERPATH_D3D10:
11357                 case RENDERPATH_D3D11:
11358                 case RENDERPATH_SOFT:
11359                 case RENDERPATH_GLES2:
11360                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11361                         break;
11362                 case RENDERPATH_GL11:
11363                 case RENDERPATH_GL13:
11364                 case RENDERPATH_GLES1:
11365                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11366                         break;
11367                 }
11368         }
11369         else
11370         {
11371                 switch (vid.renderpath)
11372                 {
11373                 case RENDERPATH_GL20:
11374                 case RENDERPATH_D3D9:
11375                 case RENDERPATH_D3D10:
11376                 case RENDERPATH_D3D11:
11377                 case RENDERPATH_SOFT:
11378                 case RENDERPATH_GLES2:
11379                         RSurf_ActiveModelEntity(ent, true, true, false);
11380                         break;
11381                 case RENDERPATH_GL11:
11382                 case RENDERPATH_GL13:
11383                 case RENDERPATH_GLES1:
11384                         RSurf_ActiveModelEntity(ent, true, false, false);
11385                         break;
11386                 }
11387         }
11388
11389         surfaces = model->data_surfaces;
11390         update = model->brushq1.lightmapupdateflags;
11391
11392         // update light styles
11393         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11394         {
11395                 model_brush_lightstyleinfo_t *style;
11396                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11397                 {
11398                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11399                         {
11400                                 int *list = style->surfacelist;
11401                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11402                                 for (j = 0;j < style->numsurfaces;j++)
11403                                         update[list[j]] = true;
11404                         }
11405                 }
11406         }
11407
11408         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11409
11410         if (debug)
11411         {
11412                 R_DrawDebugModel();
11413                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11414                 return;
11415         }
11416
11417         rsurface.lightmaptexture = NULL;
11418         rsurface.deluxemaptexture = NULL;
11419         rsurface.uselightmaptexture = false;
11420         rsurface.texture = NULL;
11421         rsurface.rtlight = NULL;
11422         numsurfacelist = 0;
11423         // add visible surfaces to draw list
11424         for (i = 0;i < model->nummodelsurfaces;i++)
11425                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11426         // don't do anything if there were no surfaces
11427         if (!numsurfacelist)
11428         {
11429                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11430                 return;
11431         }
11432         // update lightmaps if needed
11433         if (update)
11434         {
11435                 int updated = 0;
11436                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11437                 {
11438                         if (update[j])
11439                         {
11440                                 updated++;
11441                                 R_BuildLightMap(ent, surfaces + j);
11442                         }
11443                 }
11444         }
11445         if (update)
11446                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11447                         if (update[j])
11448                                 R_BuildLightMap(ent, surfaces + j);
11449         R_QueueModelSurfaceList(ent, 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.entities_surfaces += numsurfacelist;
11455                 for (j = 0;j < numsurfacelist;j++)
11456                         r_refdef.stats.entities_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_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11463 {
11464         static texture_t texture;
11465         static msurface_t surface;
11466         const msurface_t *surfacelist = &surface;
11467
11468         // fake enough texture and surface state to render this geometry
11469
11470         texture.update_lastrenderframe = -1; // regenerate this texture
11471         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11472         texture.currentskinframe = skinframe;
11473         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11474         texture.offsetmapping = OFFSETMAPPING_OFF;
11475         texture.offsetscale = 1;
11476         texture.specularscalemod = 1;
11477         texture.specularpowermod = 1;
11478
11479         surface.texture = &texture;
11480         surface.num_triangles = numtriangles;
11481         surface.num_firsttriangle = firsttriangle;
11482         surface.num_vertices = numvertices;
11483         surface.num_firstvertex = firstvertex;
11484
11485         // now render it
11486         rsurface.texture = R_GetCurrentTexture(surface.texture);
11487         rsurface.lightmaptexture = NULL;
11488         rsurface.deluxemaptexture = NULL;
11489         rsurface.uselightmaptexture = false;
11490         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11491 }
11492
11493 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)
11494 {
11495         static msurface_t surface;
11496         const msurface_t *surfacelist = &surface;
11497
11498         // fake enough texture and surface state to render this geometry
11499         surface.texture = texture;
11500         surface.num_triangles = numtriangles;
11501         surface.num_firsttriangle = firsttriangle;
11502         surface.num_vertices = numvertices;
11503         surface.num_firstvertex = firstvertex;
11504
11505         // now render it
11506         rsurface.texture = R_GetCurrentTexture(surface.texture);
11507         rsurface.lightmaptexture = NULL;
11508         rsurface.deluxemaptexture = NULL;
11509         rsurface.uselightmaptexture = false;
11510         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11511 }