]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
ffb11d702c8f86790cc5c89a5e70f0f4837dae2c
[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 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 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)"};
150 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"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
185
186 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)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 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"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 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"};
223
224 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"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 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"};
237
238 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, requires mod_q3shader_force_terrain_alphaflag on."};
239
240 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)"};
241 cvar_t r_bufferdatasize[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_bufferdatasize_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
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                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"}
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_OffsetMapping_LodDistance;
825         int loc_OffsetMapping_Bias;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_Skeletal_Transform12;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857         /// uniform block bindings
858         int ubibind_Skeletal_Transform12_UniformBlock;
859         /// uniform block indices
860         int ubiloc_Skeletal_Transform12_UniformBlock;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
884 };
885 #define SHADERSTATICPARMS_COUNT 13
886
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
889
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
892
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
896 {
897         static int r_compileshader_staticparms_save[1];
898         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
900
901         // detect all
902         if (r_glsl_saturation_redcompensate.integer)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904         if (r_glsl_vertextextureblend_usebothalphas.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906         if (r_shadow_glossexact.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908         if (r_glsl_postprocess.integer)
909         {
910                 if (r_glsl_postprocess_uservec1_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912                 if (r_glsl_postprocess_uservec2_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914                 if (r_glsl_postprocess_uservec3_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916                 if (r_glsl_postprocess_uservec4_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
918         }
919         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
921
922         if (r_shadow_shadowmapsampler)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924         if (r_shadow_shadowmappcf > 1)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926         else if (r_shadow_shadowmappcf)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928         if (r_celshading.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930         if (r_celoutlines.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
932
933         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
934 }
935
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
939         else \
940                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
942 {
943         shaderstaticparms_count = 0;
944
945         // emit all
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
959 }
960
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
967
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
969 {
970         //unsigned int hashdepth = 0;
971         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972         r_glsl_permutation_t *p;
973         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
974         {
975                 if (p->mode == mode && p->permutation == permutation)
976                 {
977                         //if (hashdepth > 10)
978                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
979                         return p;
980                 }
981                 //hashdepth++;
982         }
983         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
984         p->mode = mode;
985         p->permutation = permutation;
986         p->hashnext = r_glsl_permutationhash[mode][hashindex];
987         r_glsl_permutationhash[mode][hashindex] = p;
988         //if (hashdepth > 10)
989         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
990         return p;
991 }
992
993 static char *R_ShaderStrCat(const char **strings)
994 {
995         char *string, *s;
996         const char **p = strings;
997         const char *t;
998         size_t len = 0;
999         for (p = strings;(t = *p);p++)
1000                 len += strlen(t);
1001         len++;
1002         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1003         len = 0;
1004         for (p = strings;(t = *p);p++)
1005         {
1006                 len = strlen(t);
1007                 memcpy(s, t, len);
1008                 s += len;
1009         }
1010         *s = 0;
1011         return string;
1012 }
1013
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1015 {
1016         char *shaderstring;
1017         if (!filename || !filename[0])
1018                 return NULL;
1019         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020         if (!strcmp(filename, "glsl/default.glsl"))
1021         {
1022                 if (builtinonly)
1023                         return R_ShaderStrCat(builtinshaderstrings);
1024                 if (!glslshaderstring)
1025                 {
1026                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027                         if (glslshaderstring)
1028                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1029                         else
1030                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1031                 }
1032                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034                 return shaderstring;
1035         }
1036         if (!strcmp(filename, "hlsl/default.hlsl"))
1037         {
1038                 if (builtinonly)
1039                         return R_ShaderStrCat(builtinhlslshaderstrings);
1040                 if (!hlslshaderstring)
1041                 {
1042                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043                         if (hlslshaderstring)
1044                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1045                         else
1046                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1047                 }
1048                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050                 return shaderstring;
1051         }
1052         // we don't have builtin strings for any other files
1053         if (builtinonly)
1054                 return NULL;
1055         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056         if (shaderstring)
1057         {
1058                 if (printfromdisknotice)
1059                         Con_DPrintf("from disk %s... ", filename);
1060                 return shaderstring;
1061         }
1062         return shaderstring;
1063 }
1064
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1066 {
1067         int i;
1068         int ubibind;
1069         int sampler;
1070         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1071         char *sourcestring;
1072         char permutationname[256];
1073         int vertstrings_count = 0;
1074         int geomstrings_count = 0;
1075         int fragstrings_count = 0;
1076         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1079
1080         if (p->compiled)
1081                 return;
1082         p->compiled = true;
1083         p->program = 0;
1084
1085         permutationname[0] = 0;
1086         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1087
1088         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1089
1090         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091         if(vid.support.glshaderversion >= 140)
1092         {
1093                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1099         }
1100         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101         else if(vid.support.glshaderversion >= 130)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1167                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1168                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1169                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1170                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1171                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1172                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1173                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1174                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1175                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1176                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1177                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1178                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1179                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1180                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1181                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1182                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1183                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1184                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1185                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1186                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1187                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1188                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1189                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1190                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1191                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1192                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1193                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1194                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1195                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1196                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1197                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1198                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1199                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1200                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1201                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1202                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1203                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1204                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1205                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1206                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1207                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1208                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1209                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1210                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1211                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1212                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1213                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1214                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1215                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1216                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1217                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1218                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1219                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1220                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1221                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1222                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1223                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1224                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1225                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1226                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1227                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1228                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1229                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1230                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1231                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1232                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1233                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1234                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1235                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1236                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1237                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1238                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1239                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1240                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1241                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1242                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1243                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1244                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1245                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1246                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1247                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1248                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1249                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1250                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1251                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1252                 // initialize the samplers to refer to the texture units we use
1253                 p->tex_Texture_First = -1;
1254                 p->tex_Texture_Second = -1;
1255                 p->tex_Texture_GammaRamps = -1;
1256                 p->tex_Texture_Normal = -1;
1257                 p->tex_Texture_Color = -1;
1258                 p->tex_Texture_Gloss = -1;
1259                 p->tex_Texture_Glow = -1;
1260                 p->tex_Texture_SecondaryNormal = -1;
1261                 p->tex_Texture_SecondaryColor = -1;
1262                 p->tex_Texture_SecondaryGloss = -1;
1263                 p->tex_Texture_SecondaryGlow = -1;
1264                 p->tex_Texture_Pants = -1;
1265                 p->tex_Texture_Shirt = -1;
1266                 p->tex_Texture_FogHeightTexture = -1;
1267                 p->tex_Texture_FogMask = -1;
1268                 p->tex_Texture_Lightmap = -1;
1269                 p->tex_Texture_Deluxemap = -1;
1270                 p->tex_Texture_Attenuation = -1;
1271                 p->tex_Texture_Cube = -1;
1272                 p->tex_Texture_Refraction = -1;
1273                 p->tex_Texture_Reflection = -1;
1274                 p->tex_Texture_ShadowMap2D = -1;
1275                 p->tex_Texture_CubeProjection = -1;
1276                 p->tex_Texture_ScreenNormalMap = -1;
1277                 p->tex_Texture_ScreenDiffuse = -1;
1278                 p->tex_Texture_ScreenSpecular = -1;
1279                 p->tex_Texture_ReflectMask = -1;
1280                 p->tex_Texture_ReflectCube = -1;
1281                 p->tex_Texture_BounceGrid = -1;
1282                 // bind the texture samplers in use
1283                 sampler = 0;
1284                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1285                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1286                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1287                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1288                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1289                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1290                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1291                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1292                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1293                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1294                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1295                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1296                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1297                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1298                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1299                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1300                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1301                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1302                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1303                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1304                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1305                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1306                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1307                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1308                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1309                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1310                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1311                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1312                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1313                 // get the uniform block indices so we can bind them
1314                 if (vid.support.arb_uniform_buffer_object)
1315                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1316                 else
1317                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1318                 // clear the uniform block bindings
1319                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1320                 // bind the uniform blocks in use
1321                 ubibind = 0;
1322                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1323                 // we're done compiling and setting up the shader, at least until it is used
1324                 CHECKGLERROR
1325                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1326         }
1327         else
1328                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1329
1330         // free the strings
1331         if (sourcestring)
1332                 Mem_Free(sourcestring);
1333 }
1334
1335 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1336 {
1337         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1338         if (r_glsl_permutation != perm)
1339         {
1340                 r_glsl_permutation = perm;
1341                 if (!r_glsl_permutation->program)
1342                 {
1343                         if (!r_glsl_permutation->compiled)
1344                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1345                         if (!r_glsl_permutation->program)
1346                         {
1347                                 // remove features until we find a valid permutation
1348                                 int i;
1349                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1350                                 {
1351                                         // reduce i more quickly whenever it would not remove any bits
1352                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1353                                         if (!(permutation & j))
1354                                                 continue;
1355                                         permutation -= j;
1356                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1357                                         if (!r_glsl_permutation->compiled)
1358                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1359                                         if (r_glsl_permutation->program)
1360                                                 break;
1361                                 }
1362                                 if (i >= SHADERPERMUTATION_COUNT)
1363                                 {
1364                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1365                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1366                                         qglUseProgram(0);CHECKGLERROR
1367                                         return; // no bit left to clear, entire mode is broken
1368                                 }
1369                         }
1370                 }
1371                 CHECKGLERROR
1372                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1373         }
1374         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1375         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1376         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1377 }
1378
1379 #ifdef SUPPORTD3D
1380
1381 #ifdef SUPPORTD3D
1382 #include <d3d9.h>
1383 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1384 extern D3DCAPS9 vid_d3d9caps;
1385 #endif
1386
1387 struct r_hlsl_permutation_s;
1388 typedef struct r_hlsl_permutation_s
1389 {
1390         /// hash lookup data
1391         struct r_hlsl_permutation_s *hashnext;
1392         unsigned int mode;
1393         unsigned int permutation;
1394
1395         /// indicates if we have tried compiling this permutation already
1396         qboolean compiled;
1397         /// NULL if compilation failed
1398         IDirect3DVertexShader9 *vertexshader;
1399         IDirect3DPixelShader9 *pixelshader;
1400 }
1401 r_hlsl_permutation_t;
1402
1403 typedef enum D3DVSREGISTER_e
1404 {
1405         D3DVSREGISTER_TexMatrix = 0, // float4x4
1406         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1407         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1408         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1409         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1410         D3DVSREGISTER_ModelToLight = 20, // float4x4
1411         D3DVSREGISTER_EyePosition = 24,
1412         D3DVSREGISTER_FogPlane = 25,
1413         D3DVSREGISTER_LightDir = 26,
1414         D3DVSREGISTER_LightPosition = 27,
1415 }
1416 D3DVSREGISTER_t;
1417
1418 typedef enum D3DPSREGISTER_e
1419 {
1420         D3DPSREGISTER_Alpha = 0,
1421         D3DPSREGISTER_BloomBlur_Parameters = 1,
1422         D3DPSREGISTER_ClientTime = 2,
1423         D3DPSREGISTER_Color_Ambient = 3,
1424         D3DPSREGISTER_Color_Diffuse = 4,
1425         D3DPSREGISTER_Color_Specular = 5,
1426         D3DPSREGISTER_Color_Glow = 6,
1427         D3DPSREGISTER_Color_Pants = 7,
1428         D3DPSREGISTER_Color_Shirt = 8,
1429         D3DPSREGISTER_DeferredColor_Ambient = 9,
1430         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1431         D3DPSREGISTER_DeferredColor_Specular = 11,
1432         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1433         D3DPSREGISTER_DeferredMod_Specular = 13,
1434         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1435         D3DPSREGISTER_EyePosition = 15, // unused
1436         D3DPSREGISTER_FogColor = 16,
1437         D3DPSREGISTER_FogHeightFade = 17,
1438         D3DPSREGISTER_FogPlane = 18,
1439         D3DPSREGISTER_FogPlaneViewDist = 19,
1440         D3DPSREGISTER_FogRangeRecip = 20,
1441         D3DPSREGISTER_LightColor = 21,
1442         D3DPSREGISTER_LightDir = 22, // unused
1443         D3DPSREGISTER_LightPosition = 23,
1444         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1445         D3DPSREGISTER_PixelSize = 25,
1446         D3DPSREGISTER_ReflectColor = 26,
1447         D3DPSREGISTER_ReflectFactor = 27,
1448         D3DPSREGISTER_ReflectOffset = 28,
1449         D3DPSREGISTER_RefractColor = 29,
1450         D3DPSREGISTER_Saturation = 30,
1451         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1452         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1453         D3DPSREGISTER_ScreenToDepth = 33,
1454         D3DPSREGISTER_ShadowMap_Parameters = 34,
1455         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1456         D3DPSREGISTER_SpecularPower = 36,
1457         D3DPSREGISTER_UserVec1 = 37,
1458         D3DPSREGISTER_UserVec2 = 38,
1459         D3DPSREGISTER_UserVec3 = 39,
1460         D3DPSREGISTER_UserVec4 = 40,
1461         D3DPSREGISTER_ViewTintColor = 41,
1462         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1463         D3DPSREGISTER_BloomColorSubtract = 43,
1464         D3DPSREGISTER_ViewToLight = 44, // float4x4
1465         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1466         D3DPSREGISTER_NormalmapScrollBlend = 52,
1467         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1468         D3DPSREGISTER_OffsetMapping_Bias = 54,
1469         // next at 54
1470 }
1471 D3DPSREGISTER_t;
1472
1473 /// information about each possible shader permutation
1474 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1475 /// currently selected permutation
1476 r_hlsl_permutation_t *r_hlsl_permutation;
1477 /// storage for permutations linked in the hash table
1478 memexpandablearray_t r_hlsl_permutationarray;
1479
1480 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1481 {
1482         //unsigned int hashdepth = 0;
1483         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1484         r_hlsl_permutation_t *p;
1485         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1486         {
1487                 if (p->mode == mode && p->permutation == permutation)
1488                 {
1489                         //if (hashdepth > 10)
1490                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1491                         return p;
1492                 }
1493                 //hashdepth++;
1494         }
1495         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1496         p->mode = mode;
1497         p->permutation = permutation;
1498         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1499         r_hlsl_permutationhash[mode][hashindex] = p;
1500         //if (hashdepth > 10)
1501         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1502         return p;
1503 }
1504
1505 #include <d3dx9.h>
1506 //#include <d3dx9shader.h>
1507 //#include <d3dx9mesh.h>
1508
1509 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1510 {
1511         DWORD *vsbin = NULL;
1512         DWORD *psbin = NULL;
1513         fs_offset_t vsbinsize;
1514         fs_offset_t psbinsize;
1515 //      IDirect3DVertexShader9 *vs = NULL;
1516 //      IDirect3DPixelShader9 *ps = NULL;
1517         ID3DXBuffer *vslog = NULL;
1518         ID3DXBuffer *vsbuffer = NULL;
1519         ID3DXConstantTable *vsconstanttable = NULL;
1520         ID3DXBuffer *pslog = NULL;
1521         ID3DXBuffer *psbuffer = NULL;
1522         ID3DXConstantTable *psconstanttable = NULL;
1523         int vsresult = 0;
1524         int psresult = 0;
1525         char temp[MAX_INPUTLINE];
1526         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1527         char vabuf[1024];
1528         qboolean debugshader = gl_paranoid.integer != 0;
1529         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1530         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531         if (!debugshader)
1532         {
1533                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1534                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1535         }
1536         if ((!vsbin && vertstring) || (!psbin && fragstring))
1537         {
1538                 const char* dllnames_d3dx9 [] =
1539                 {
1540                         "d3dx9_43.dll",
1541                         "d3dx9_42.dll",
1542                         "d3dx9_41.dll",
1543                         "d3dx9_40.dll",
1544                         "d3dx9_39.dll",
1545                         "d3dx9_38.dll",
1546                         "d3dx9_37.dll",
1547                         "d3dx9_36.dll",
1548                         "d3dx9_35.dll",
1549                         "d3dx9_34.dll",
1550                         "d3dx9_33.dll",
1551                         "d3dx9_32.dll",
1552                         "d3dx9_31.dll",
1553                         "d3dx9_30.dll",
1554                         "d3dx9_29.dll",
1555                         "d3dx9_28.dll",
1556                         "d3dx9_27.dll",
1557                         "d3dx9_26.dll",
1558                         "d3dx9_25.dll",
1559                         "d3dx9_24.dll",
1560                         NULL
1561                 };
1562                 dllhandle_t d3dx9_dll = NULL;
1563                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1564                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1565                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1566                 dllfunction_t d3dx9_dllfuncs[] =
1567                 {
1568                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1569                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1570                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1571                         {NULL, NULL}
1572                 };
1573                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1574 #ifndef ID3DXBuffer_GetBufferPointer
1575 #if !defined(__cplusplus) || defined(CINTERFACE)
1576 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1577 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1578 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1579 #else
1580 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1581 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1582 #define ID3DXBuffer_Release(p)            (p)->Release()
1583 #endif
1584 #endif
1585                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1586                 {
1587                         DWORD shaderflags = 0;
1588                         if (debugshader)
1589                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1590                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1591                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1592                         if (vertstring && vertstring[0])
1593                         {
1594                                 if (debugshader)
1595                                 {
1596                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1597                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1598                                 }
1599                                 else
1600                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1601                                 if (vsbuffer)
1602                                 {
1603                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1604                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1605                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1606                                         ID3DXBuffer_Release(vsbuffer);
1607                                 }
1608                                 if (vslog)
1609                                 {
1610                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1611                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1612                                         ID3DXBuffer_Release(vslog);
1613                                 }
1614                         }
1615                         if (fragstring && fragstring[0])
1616                         {
1617                                 if (debugshader)
1618                                 {
1619                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1620                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1621                                 }
1622                                 else
1623                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1624                                 if (psbuffer)
1625                                 {
1626                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1627                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1628                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1629                                         ID3DXBuffer_Release(psbuffer);
1630                                 }
1631                                 if (pslog)
1632                                 {
1633                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1634                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1635                                         ID3DXBuffer_Release(pslog);
1636                                 }
1637                         }
1638                         Sys_UnloadLibrary(&d3dx9_dll);
1639                 }
1640                 else
1641                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1642         }
1643         if (vsbin && psbin)
1644         {
1645                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1646                 if (FAILED(vsresult))
1647                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1648                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1649                 if (FAILED(psresult))
1650                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1651         }
1652         // free the shader data
1653         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1654         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1655 }
1656
1657 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1658 {
1659         int i;
1660         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1661         int vertstring_length = 0;
1662         int geomstring_length = 0;
1663         int fragstring_length = 0;
1664         char *t;
1665         char *sourcestring;
1666         char *vertstring, *geomstring, *fragstring;
1667         char permutationname[256];
1668         char cachename[256];
1669         int vertstrings_count = 0;
1670         int geomstrings_count = 0;
1671         int fragstrings_count = 0;
1672         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1673         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675
1676         if (p->compiled)
1677                 return;
1678         p->compiled = true;
1679         p->vertexshader = NULL;
1680         p->pixelshader = NULL;
1681
1682         permutationname[0] = 0;
1683         cachename[0] = 0;
1684         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1685
1686         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1687         strlcat(cachename, "hlsl/", sizeof(cachename));
1688
1689         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1690         vertstrings_count = 0;
1691         geomstrings_count = 0;
1692         fragstrings_count = 0;
1693         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1694         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1695         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1696
1697         // the first pretext is which type of shader to compile as
1698         // (later these will all be bound together as a program object)
1699         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1700         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1701         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1702
1703         // the second pretext is the mode (for example a light source)
1704         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1705         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1706         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1707         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1708         strlcat(cachename, modeinfo->name, sizeof(cachename));
1709
1710         // now add all the permutation pretexts
1711         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1712         {
1713                 if (permutation & (1<<i))
1714                 {
1715                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1716                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1717                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1718                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1719                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1720                 }
1721                 else
1722                 {
1723                         // keep line numbers correct
1724                         vertstrings_list[vertstrings_count++] = "\n";
1725                         geomstrings_list[geomstrings_count++] = "\n";
1726                         fragstrings_list[fragstrings_count++] = "\n";
1727                 }
1728         }
1729
1730         // add static parms
1731         R_CompileShader_AddStaticParms(mode, permutation);
1732         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1733         vertstrings_count += shaderstaticparms_count;
1734         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1735         geomstrings_count += shaderstaticparms_count;
1736         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1737         fragstrings_count += shaderstaticparms_count;
1738
1739         // replace spaces in the cachename with _ characters
1740         for (i = 0;cachename[i];i++)
1741                 if (cachename[i] == ' ')
1742                         cachename[i] = '_';
1743
1744         // now append the shader text itself
1745         vertstrings_list[vertstrings_count++] = sourcestring;
1746         geomstrings_list[geomstrings_count++] = sourcestring;
1747         fragstrings_list[fragstrings_count++] = sourcestring;
1748
1749         vertstring_length = 0;
1750         for (i = 0;i < vertstrings_count;i++)
1751                 vertstring_length += strlen(vertstrings_list[i]);
1752         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1753         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1754                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1755
1756         geomstring_length = 0;
1757         for (i = 0;i < geomstrings_count;i++)
1758                 geomstring_length += strlen(geomstrings_list[i]);
1759         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1760         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1761                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1762
1763         fragstring_length = 0;
1764         for (i = 0;i < fragstrings_count;i++)
1765                 fragstring_length += strlen(fragstrings_list[i]);
1766         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1767         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1768                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1769
1770         // try to load the cached shader, or generate one
1771         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1772
1773         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1774                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1775         else
1776                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1777
1778         // free the strings
1779         if (vertstring)
1780                 Mem_Free(vertstring);
1781         if (geomstring)
1782                 Mem_Free(geomstring);
1783         if (fragstring)
1784                 Mem_Free(fragstring);
1785         if (sourcestring)
1786                 Mem_Free(sourcestring);
1787 }
1788
1789 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1790 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1791 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);}
1792 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);}
1793 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);}
1794 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);}
1795
1796 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1797 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1798 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);}
1799 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);}
1800 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);}
1801 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);}
1802
1803 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1804 {
1805         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1806         if (r_hlsl_permutation != perm)
1807         {
1808                 r_hlsl_permutation = perm;
1809                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1810                 {
1811                         if (!r_hlsl_permutation->compiled)
1812                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1813                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1814                         {
1815                                 // remove features until we find a valid permutation
1816                                 int i;
1817                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1818                                 {
1819                                         // reduce i more quickly whenever it would not remove any bits
1820                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1821                                         if (!(permutation & j))
1822                                                 continue;
1823                                         permutation -= j;
1824                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1825                                         if (!r_hlsl_permutation->compiled)
1826                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1827                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1828                                                 break;
1829                                 }
1830                                 if (i >= SHADERPERMUTATION_COUNT)
1831                                 {
1832                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1833                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1834                                         return; // no bit left to clear, entire mode is broken
1835                                 }
1836                         }
1837                 }
1838                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1839                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1840         }
1841         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1842         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1843         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1844 }
1845 #endif
1846
1847 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1848 {
1849         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1850         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1851         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1852         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1853 }
1854
1855 void R_GLSL_Restart_f(void)
1856 {
1857         unsigned int i, limit;
1858         if (glslshaderstring)
1859                 Mem_Free(glslshaderstring);
1860         glslshaderstring = NULL;
1861         if (hlslshaderstring)
1862                 Mem_Free(hlslshaderstring);
1863         hlslshaderstring = NULL;
1864         switch(vid.renderpath)
1865         {
1866         case RENDERPATH_D3D9:
1867 #ifdef SUPPORTD3D
1868                 {
1869                         r_hlsl_permutation_t *p;
1870                         r_hlsl_permutation = NULL;
1871                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1872                         for (i = 0;i < limit;i++)
1873                         {
1874                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1875                                 {
1876                                         if (p->vertexshader)
1877                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1878                                         if (p->pixelshader)
1879                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1880                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1881                                 }
1882                         }
1883                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1884                 }
1885 #endif
1886                 break;
1887         case RENDERPATH_D3D10:
1888                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_D3D11:
1891                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_GL20:
1894         case RENDERPATH_GLES2:
1895                 {
1896                         r_glsl_permutation_t *p;
1897                         r_glsl_permutation = NULL;
1898                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1899                         for (i = 0;i < limit;i++)
1900                         {
1901                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1902                                 {
1903                                         GL_Backend_FreeProgram(p->program);
1904                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1905                                 }
1906                         }
1907                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1908                 }
1909                 break;
1910         case RENDERPATH_GL11:
1911         case RENDERPATH_GL13:
1912         case RENDERPATH_GLES1:
1913                 break;
1914         case RENDERPATH_SOFT:
1915                 break;
1916         }
1917 }
1918
1919 static void R_GLSL_DumpShader_f(void)
1920 {
1921         int i, language, mode, dupe;
1922         char *text;
1923         shadermodeinfo_t *modeinfo;
1924         qfile_t *file;
1925
1926         for (language = 0;language < 2;language++)
1927         {
1928                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1929                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1930                 {
1931                         // don't dump the same file multiple times (most or all shaders come from the same file)
1932                         for (dupe = mode - 1;dupe >= 0;dupe--)
1933                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1934                                         break;
1935                         if (dupe >= 0)
1936                                 continue;
1937                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1938                         if (!text)
1939                                 continue;
1940                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1941                         if (file)
1942                         {
1943                                 FS_Print(file, "/* The engine may define the following macros:\n");
1944                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1945                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1946                                         FS_Print(file, modeinfo[i].pretext);
1947                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1948                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1949                                 FS_Print(file, "*/\n");
1950                                 FS_Print(file, text);
1951                                 FS_Close(file);
1952                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1953                         }
1954                         else
1955                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1956                         Mem_Free(text);
1957                 }
1958         }
1959 }
1960
1961 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1962 {
1963         unsigned int permutation = 0;
1964         if (r_trippy.integer && !notrippy)
1965                 permutation |= SHADERPERMUTATION_TRIPPY;
1966         permutation |= SHADERPERMUTATION_VIEWTINT;
1967         if (first)
1968                 permutation |= SHADERPERMUTATION_DIFFUSE;
1969         if (second)
1970                 permutation |= SHADERPERMUTATION_SPECULAR;
1971         if (texturemode == GL_MODULATE)
1972                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1973         else if (texturemode == GL_ADD)
1974                 permutation |= SHADERPERMUTATION_GLOW;
1975         else if (texturemode == GL_DECAL)
1976                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1977         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1978                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1979         if (suppresstexalpha)
1980                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1981         if (!second)
1982                 texturemode = GL_MODULATE;
1983         if (vid.allowalphatocoverage)
1984                 GL_AlphaToCoverage(false);
1985         switch (vid.renderpath)
1986         {
1987         case RENDERPATH_D3D9:
1988 #ifdef SUPPORTD3D
1989                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1990                 R_Mesh_TexBind(GL20TU_FIRST , first );
1991                 R_Mesh_TexBind(GL20TU_SECOND, second);
1992                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1993                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2005                 if (r_glsl_permutation->tex_Texture_First >= 0)
2006                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2007                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2008                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2009                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2010                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2011                 break;
2012         case RENDERPATH_GL13:
2013         case RENDERPATH_GLES1:
2014                 R_Mesh_TexBind(0, first );
2015                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2016                 R_Mesh_TexMatrix(0, NULL);
2017                 R_Mesh_TexBind(1, second);
2018                 if (second)
2019                 {
2020                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2021                         R_Mesh_TexMatrix(1, NULL);
2022                 }
2023                 break;
2024         case RENDERPATH_GL11:
2025                 R_Mesh_TexBind(0, first );
2026                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2027                 R_Mesh_TexMatrix(0, NULL);
2028                 break;
2029         case RENDERPATH_SOFT:
2030                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2031                 R_Mesh_TexBind(GL20TU_FIRST , first );
2032                 R_Mesh_TexBind(GL20TU_SECOND, second);
2033                 break;
2034         }
2035 }
2036
2037 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2038 {
2039         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2040 }
2041
2042 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2043 {
2044         unsigned int permutation = 0;
2045         if (r_trippy.integer && !notrippy)
2046                 permutation |= SHADERPERMUTATION_TRIPPY;
2047         if (depthrgb)
2048                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2049         if (skeletal)
2050                 permutation |= SHADERPERMUTATION_SKELETAL;
2051
2052         if (vid.allowalphatocoverage)
2053                 GL_AlphaToCoverage(false);
2054         switch (vid.renderpath)
2055         {
2056         case RENDERPATH_D3D9:
2057 #ifdef SUPPORTD3D
2058                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2059 #endif
2060                 break;
2061         case RENDERPATH_D3D10:
2062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063                 break;
2064         case RENDERPATH_D3D11:
2065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2066                 break;
2067         case RENDERPATH_GL20:
2068         case RENDERPATH_GLES2:
2069                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2070                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, 0);
2075                 R_Mesh_TexBind(1, 0);
2076                 break;
2077         case RENDERPATH_GL11:
2078                 R_Mesh_TexBind(0, 0);
2079                 break;
2080         case RENDERPATH_SOFT:
2081                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2082                 break;
2083         }
2084 }
2085
2086 extern qboolean r_shadow_usingdeferredprepass;
2087 extern rtexture_t *r_shadow_attenuationgradienttexture;
2088 extern rtexture_t *r_shadow_attenuation2dtexture;
2089 extern rtexture_t *r_shadow_attenuation3dtexture;
2090 extern qboolean r_shadow_usingshadowmap2d;
2091 extern qboolean r_shadow_usingshadowmaportho;
2092 extern float r_shadow_shadowmap_texturescale[2];
2093 extern float r_shadow_shadowmap_parameters[4];
2094 extern qboolean r_shadow_shadowmapvsdct;
2095 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2097 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2098 extern matrix4x4_t r_shadow_shadowmapmatrix;
2099 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2100 extern int r_shadow_prepass_width;
2101 extern int r_shadow_prepass_height;
2102 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2103 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2104 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2105 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2106
2107 #define BLENDFUNC_ALLOWS_COLORMOD      1
2108 #define BLENDFUNC_ALLOWS_FOG           2
2109 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2110 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2111 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2112 static int R_BlendFuncFlags(int src, int dst)
2113 {
2114         int r = 0;
2115
2116         // a blendfunc allows colormod if:
2117         // a) it can never keep the destination pixel invariant, or
2118         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2119         // this is to prevent unintended side effects from colormod
2120
2121         // a blendfunc allows fog if:
2122         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2123         // this is to prevent unintended side effects from fog
2124
2125         // these checks are the output of fogeval.pl
2126
2127         r |= BLENDFUNC_ALLOWS_COLORMOD;
2128         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2136         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2137         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2138         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2140         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2141         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2142         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2143         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2144         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2146         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2147         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2148         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2149
2150         return r;
2151 }
2152
2153 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2154 {
2155         // select a permutation of the lighting shader appropriate to this
2156         // combination of texture, entity, light source, and fogging, only use the
2157         // minimum features necessary to avoid wasting rendering time in the
2158         // fragment shader on features that are not being used
2159         unsigned int permutation = 0;
2160         unsigned int mode = 0;
2161         int blendfuncflags;
2162         static float dummy_colormod[3] = {1, 1, 1};
2163         float *colormod = rsurface.colormod;
2164         float m16f[16];
2165         matrix4x4_t tempmatrix;
2166         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2167         if (r_trippy.integer && !notrippy)
2168                 permutation |= SHADERPERMUTATION_TRIPPY;
2169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2170                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2171         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2172                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2173         if (rsurfacepass == RSURFPASS_BACKGROUND)
2174         {
2175                 // distorted background
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2177                 {
2178                         mode = SHADERMODE_WATER;
2179                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2180                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2181                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2182                         {
2183                                 // this is the right thing to do for wateralpha
2184                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2185                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2186                         }
2187                         else
2188                         {
2189                                 // this is the right thing to do for entity alpha
2190                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2191                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                         }
2193                 }
2194                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2195                 {
2196                         mode = SHADERMODE_REFRACTION;
2197                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2198                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2200                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201                 }
2202                 else
2203                 {
2204                         mode = SHADERMODE_GENERIC;
2205                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2206                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2207                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208                 }
2209                 if (vid.allowalphatocoverage)
2210                         GL_AlphaToCoverage(false);
2211         }
2212         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2213         {
2214                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2215                 {
2216                         switch(rsurface.texture->offsetmapping)
2217                         {
2218                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_OFF: break;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // normalmap (deferred prepass), may use alpha test on diffuse
2227                 mode = SHADERMODE_DEFERREDGEOMETRY;
2228                 GL_BlendFunc(GL_ONE, GL_ZERO);
2229                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249                 // light source
2250                 mode = SHADERMODE_LIGHTSOURCE;
2251                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2252                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2253                 if (diffusescale > 0)
2254                         permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmap2d)
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264                         if(r_shadow_shadowmapvsdct)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2266
2267                         if (r_shadow_shadowmap2ddepthbuffer)
2268                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2269                 }
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2273                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2274                 if (vid.allowalphatocoverage)
2275                         GL_AlphaToCoverage(false);
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2292                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2293                 // unshaded geometry (fullbright or ambient model lighting)
2294                 mode = SHADERMODE_FLATCOLOR;
2295                 ambientscale = diffusescale = specularscale = 0;
2296                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmap2ddepthbuffer)
2308                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311                         permutation |= SHADERPERMUTATION_REFLECTION;
2312                 if (rsurface.texture->reflectmasktexture)
2313                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2314                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2315                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316                 // when using alphatocoverage, we don't need alphakill
2317                 if (vid.allowalphatocoverage)
2318                 {
2319                         if (r_transparent_alphatocoverage.integer)
2320                         {
2321                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2322                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2323                         }
2324                         else
2325                                 GL_AlphaToCoverage(false);
2326                 }
2327         }
2328         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2329         {
2330                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2331                 {
2332                         switch(rsurface.texture->offsetmapping)
2333                         {
2334                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2335                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337                         case OFFSETMAPPING_OFF: break;
2338                         }
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2343                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2344                 // directional model lighting
2345                 mode = SHADERMODE_LIGHTDIRECTION;
2346                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 permutation |= SHADERPERMUTATION_DIFFUSE;
2349                 if (specularscale > 0)
2350                         permutation |= SHADERPERMUTATION_SPECULAR;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmap2ddepthbuffer)
2361                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2370                 {
2371                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2372                         if (r_shadow_bouncegriddirectional)
2373                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2374                 }
2375                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2376                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 // when using alphatocoverage, we don't need alphakill
2378                 if (vid.allowalphatocoverage)
2379                 {
2380                         if (r_transparent_alphatocoverage.integer)
2381                         {
2382                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2383                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384                         }
2385                         else
2386                                 GL_AlphaToCoverage(false);
2387                 }
2388         }
2389         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2390         {
2391                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2392                 {
2393                         switch(rsurface.texture->offsetmapping)
2394                         {
2395                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2396                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2397                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_OFF: break;
2399                         }
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2404                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2405                 // ambient model lighting
2406                 mode = SHADERMODE_LIGHTDIRECTION;
2407                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2408                         permutation |= SHADERPERMUTATION_GLOW;
2409                 if (r_refdef.fogenabled)
2410                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2411                 if (rsurface.texture->colormapping)
2412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2413                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2414                 {
2415                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2416                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2417
2418                         if (r_shadow_shadowmap2ddepthbuffer)
2419                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2422                         permutation |= SHADERPERMUTATION_REFLECTION;
2423                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2424                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2425                 if (rsurface.texture->reflectmasktexture)
2426                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2427                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2428                 {
2429                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2430                         if (r_shadow_bouncegriddirectional)
2431                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432                 }
2433                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 // when using alphatocoverage, we don't need alphakill
2436                 if (vid.allowalphatocoverage)
2437                 {
2438                         if (r_transparent_alphatocoverage.integer)
2439                         {
2440                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2441                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2442                         }
2443                         else
2444                                 GL_AlphaToCoverage(false);
2445                 }
2446         }
2447         else
2448         {
2449                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2450                 {
2451                         switch(rsurface.texture->offsetmapping)
2452                         {
2453                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2454                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2455                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_OFF: break;
2457                         }
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2462                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2463                 // lightmapped wall
2464                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2465                         permutation |= SHADERPERMUTATION_GLOW;
2466                 if (r_refdef.fogenabled)
2467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2468                 if (rsurface.texture->colormapping)
2469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2470                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2471                 {
2472                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2474
2475                         if (r_shadow_shadowmap2ddepthbuffer)
2476                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2477                 }
2478                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2479                         permutation |= SHADERPERMUTATION_REFLECTION;
2480                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2481                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2482                 if (rsurface.texture->reflectmasktexture)
2483                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2484                 if (FAKELIGHT_ENABLED)
2485                 {
2486                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2487                         mode = SHADERMODE_FAKELIGHT;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2493                 {
2494                         // deluxemapping (light direction texture)
2495                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2497                         else
2498                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2499                         permutation |= SHADERPERMUTATION_DIFFUSE;
2500                         if (specularscale > 0)
2501                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2502                 }
2503                 else if (r_glsl_deluxemapping.integer >= 2)
2504                 {
2505                         // fake deluxemapping (uniform light direction in tangentspace)
2506                         if (rsurface.uselightmaptexture)
2507                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2508                         else
2509                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2510                         permutation |= SHADERPERMUTATION_DIFFUSE;
2511                         if (specularscale > 0)
2512                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2513                 }
2514                 else if (rsurface.uselightmaptexture)
2515                 {
2516                         // ordinary lightmapping (q1bsp, q3bsp)
2517                         mode = SHADERMODE_LIGHTMAP;
2518                 }
2519                 else
2520                 {
2521                         // ordinary vertex coloring (q3bsp)
2522                         mode = SHADERMODE_VERTEXCOLOR;
2523                 }
2524                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2525                 {
2526                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2527                         if (r_shadow_bouncegriddirectional)
2528                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2529                 }
2530                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2531                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532                 // when using alphatocoverage, we don't need alphakill
2533                 if (vid.allowalphatocoverage)
2534                 {
2535                         if (r_transparent_alphatocoverage.integer)
2536                         {
2537                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2538                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2539                         }
2540                         else
2541                                 GL_AlphaToCoverage(false);
2542                 }
2543         }
2544         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2545                 colormod = dummy_colormod;
2546         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2547                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2548         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2549                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2550         switch(vid.renderpath)
2551         {
2552         case RENDERPATH_D3D9:
2553 #ifdef SUPPORTD3D
2554                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2555                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2556                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2561                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                 }
2563                 else
2564                 {
2565                         if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2568                         }
2569                 }
2570                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2572                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2573                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2574                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2575
2576                 if (mode == SHADERMODE_LIGHTSOURCE)
2577                 {
2578                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2579                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2580                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2583
2584                         // additive passes are only darkened by fog, not tinted
2585                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2587                 }
2588                 else
2589                 {
2590                         if (mode == SHADERMODE_FLATCOLOR)
2591                         {
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2593                         }
2594                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2595                         {
2596                                 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]);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2598                                 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);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2603                         }
2604                         else
2605                         {
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2608                                 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);
2609                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2611                         }
2612                         // additive passes are only darkened by fog, not tinted
2613                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2615                         else
2616                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617                         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);
2618                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2620                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2621                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                         if (mode == SHADERMODE_WATER)
2626                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2627                 }
2628                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2630                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2631                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2632                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 if (rsurface.texture->pantstexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2637                 if (rsurface.texture->shirttexture)
2638                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2639                 else
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2641                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2642                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2643                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2644                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2645                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2646                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2647                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2648                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2650                         );
2651                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2652                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2653                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2654                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2655
2656                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2657                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2658                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2659                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2660                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2661                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2662                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2663                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2664                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2665                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2666                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2667                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2668                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2669                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2670                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2671                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2672                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2673                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2674                 {
2675                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2676                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2677                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678                 }
2679                 else
2680                 {
2681                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2682                 }
2683 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2684                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2685                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2686                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2687                 {
2688                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2689                         if (rsurface.rtlight)
2690                         {
2691                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2692                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2693                         }
2694                 }
2695 #endif
2696                 break;
2697         case RENDERPATH_D3D10:
2698                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2699                 break;
2700         case RENDERPATH_D3D11:
2701                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2702                 break;
2703         case RENDERPATH_GL20:
2704         case RENDERPATH_GLES2:
2705                 if (!vid.useinterleavedarrays)
2706                 {
2707                         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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2708                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2709                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2713                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2714                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2715                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2716                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2717                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2718                 }
2719                 else
2720                 {
2721                         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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2722                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2723                 }
2724                 // this has to be after RSurf_PrepareVerticesForBatch
2725                 if (rsurface.batchskeletaltransform3x4buffer)
2726                         permutation |= SHADERPERMUTATION_SKELETAL;
2727                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2728                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2729                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2730                 if (mode == SHADERMODE_LIGHTSOURCE)
2731                 {
2732                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2733                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2734                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2735                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2736                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2737                         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);
2738         
2739                         // additive passes are only darkened by fog, not tinted
2740                         if (r_glsl_permutation->loc_FogColor >= 0)
2741                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2742                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2743                 }
2744                 else
2745                 {
2746                         if (mode == SHADERMODE_FLATCOLOR)
2747                         {
2748                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2749                         }
2750                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2751                         {
2752                                 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]);
2753                                 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]);
2754                                 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);
2755                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2756                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2757                                 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]);
2758                                 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]);
2759                         }
2760                         else
2761                         {
2762                                 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]);
2763                                 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]);
2764                                 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);
2765                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2766                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2767                         }
2768                         // additive passes are only darkened by fog, not tinted
2769                         if (r_glsl_permutation->loc_FogColor >= 0)
2770                         {
2771                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2773                                 else
2774                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775                         }
2776                         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);
2777                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2778                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2779                         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]);
2780                         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]);
2781                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2782                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2783                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2784                         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]);
2785                 }
2786                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2787                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2788                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2789                 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]);
2790                 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]);
2791
2792                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2793                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2794                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2795                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2796                 {
2797                         if (rsurface.texture->pantstexture)
2798                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799                         else
2800                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2801                 }
2802                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2803                 {
2804                         if (rsurface.texture->shirttexture)
2805                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806                         else
2807                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2808                 }
2809                 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]);
2810                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2811                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2812                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2813                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2814                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2815                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2816                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2818                         );
2819                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2820                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2821                 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]);
2822                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2823                 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);}
2824                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2825
2826                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2827                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2828                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2829                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2830                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2831                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2832                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2833                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2834                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2835                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2836                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2837                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2838                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2839                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2840                 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);
2841                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2842                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2843                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2844                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2845                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2846                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2847                 {
2848                         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);
2849                         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);
2850                         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);
2851                 }
2852                 else
2853                 {
2854                         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);
2855                 }
2856                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2857                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2858                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2859                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2860                 {
2861                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2862                         if (rsurface.rtlight)
2863                         {
2864                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2865                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2866                         }
2867                 }
2868                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2869                 CHECKGLERROR
2870                 break;
2871         case RENDERPATH_GL11:
2872         case RENDERPATH_GL13:
2873         case RENDERPATH_GLES1:
2874                 break;
2875         case RENDERPATH_SOFT:
2876                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2877                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2878                 R_SetupShader_SetPermutationSoft(mode, permutation);
2879                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2880                 if (mode == SHADERMODE_LIGHTSOURCE)
2881                 {
2882                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2885                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2888         
2889                         // additive passes are only darkened by fog, not tinted
2890                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2892                 }
2893                 else
2894                 {
2895                         if (mode == SHADERMODE_FLATCOLOR)
2896                         {
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2898                         }
2899                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2900                         {
2901                                 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]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2903                                 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);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2906                                 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]);
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2908                         }
2909                         else
2910                         {
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2913                                 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);
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2916                         }
2917                         // additive passes are only darkened by fog, not tinted
2918                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2922                         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);
2923                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2924                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2925                         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]);
2926                         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]);
2927                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2928                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2929                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2930                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2931                 }
2932                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2933                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2934                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2935                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 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]);
2937
2938                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2940                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2941                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2942                 {
2943                         if (rsurface.texture->pantstexture)
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2945                         else
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2947                 }
2948                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2949                 {
2950                         if (rsurface.texture->shirttexture)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2954                 }
2955                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2956                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2957                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2958                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2959                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2960                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2961                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2962                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2964                         );
2965                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2966                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2971                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2972                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2973                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2974                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2975                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2976                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2977                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2978                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2979                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2980                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2981                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2982                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2983                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2984                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2985                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2986                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2987                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2988                 {
2989                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2990                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2991                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992                 }
2993                 else
2994                 {
2995                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2996                 }
2997 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2998                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2999                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3000                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3001                 {
3002                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3003                         if (rsurface.rtlight)
3004                         {
3005                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3006                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3007                         }
3008                 }
3009                 break;
3010         }
3011 }
3012
3013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3014 {
3015         // select a permutation of the lighting shader appropriate to this
3016         // combination of texture, entity, light source, and fogging, only use the
3017         // minimum features necessary to avoid wasting rendering time in the
3018         // fragment shader on features that are not being used
3019         unsigned int permutation = 0;
3020         unsigned int mode = 0;
3021         const float *lightcolorbase = rtlight->currentcolor;
3022         float ambientscale = rtlight->ambientscale;
3023         float diffusescale = rtlight->diffusescale;
3024         float specularscale = rtlight->specularscale;
3025         // this is the location of the light in view space
3026         vec3_t viewlightorigin;
3027         // this transforms from view space (camera) to light space (cubemap)
3028         matrix4x4_t viewtolight;
3029         matrix4x4_t lighttoview;
3030         float viewtolight16f[16];
3031         // light source
3032         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3033         if (rtlight->currentcubemap != r_texture_whitecube)
3034                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3035         if (diffusescale > 0)
3036                 permutation |= SHADERPERMUTATION_DIFFUSE;
3037         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3038                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3039         if (r_shadow_usingshadowmap2d)
3040         {
3041                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3042                 if (r_shadow_shadowmapvsdct)
3043                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3044
3045                 if (r_shadow_shadowmap2ddepthbuffer)
3046                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3047         }
3048         if (vid.allowalphatocoverage)
3049                 GL_AlphaToCoverage(false);
3050         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3051         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3052         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3053         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3054         switch(vid.renderpath)
3055         {
3056         case RENDERPATH_D3D9:
3057 #ifdef SUPPORTD3D
3058                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3059                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3061                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3066                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3067                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075 #endif
3076                 break;
3077         case RENDERPATH_D3D10:
3078                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079                 break;
3080         case RENDERPATH_D3D11:
3081                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3082                 break;
3083         case RENDERPATH_GL20:
3084         case RENDERPATH_GLES2:
3085                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3086                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3087                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3088                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3089                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3090                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3091                 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]);
3092                 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]);
3093                 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) - 1.0f);
3094                 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]);
3095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3096
3097                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3098                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3099                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3100                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3101                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3102                 break;
3103         case RENDERPATH_GL11:
3104         case RENDERPATH_GL13:
3105         case RENDERPATH_GLES1:
3106                 break;
3107         case RENDERPATH_SOFT:
3108                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3111                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 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]);
3116                 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) - 1.0f);
3117                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125                 break;
3126         }
3127 }
3128
3129 #define SKINFRAME_HASH 1024
3130
3131 typedef struct
3132 {
3133         int loadsequence; // incremented each level change
3134         memexpandablearray_t array;
3135         skinframe_t *hash[SKINFRAME_HASH];
3136 }
3137 r_skinframe_t;
3138 r_skinframe_t r_skinframe;
3139
3140 void R_SkinFrame_PrepareForPurge(void)
3141 {
3142         r_skinframe.loadsequence++;
3143         // wrap it without hitting zero
3144         if (r_skinframe.loadsequence >= 200)
3145                 r_skinframe.loadsequence = 1;
3146 }
3147
3148 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3149 {
3150         if (!skinframe)
3151                 return;
3152         // mark the skinframe as used for the purging code
3153         skinframe->loadsequence = r_skinframe.loadsequence;
3154 }
3155
3156 void R_SkinFrame_Purge(void)
3157 {
3158         int i;
3159         skinframe_t *s;
3160         for (i = 0;i < SKINFRAME_HASH;i++)
3161         {
3162                 for (s = r_skinframe.hash[i];s;s = s->next)
3163                 {
3164                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3165                         {
3166                                 if (s->merged == s->base)
3167                                         s->merged = NULL;
3168                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3169                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3170                                 R_PurgeTexture(s->merged);s->merged = NULL;
3171                                 R_PurgeTexture(s->base  );s->base   = NULL;
3172                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3173                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3174                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3175                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3176                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3177                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3178                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3179                                 s->loadsequence = 0;
3180                         }
3181                 }
3182         }
3183 }
3184
3185 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3186         skinframe_t *item;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         if( last == NULL ) {
3192                 int hashindex;
3193                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194                 item = r_skinframe.hash[hashindex];
3195         } else {
3196                 item = last->next;
3197         }
3198
3199         // linearly search through the hash bucket
3200         for( ; item ; item = item->next ) {
3201                 if( !strcmp( item->basename, basename ) ) {
3202                         return item;
3203                 }
3204         }
3205         return NULL;
3206 }
3207
3208 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3209 {
3210         skinframe_t *item;
3211         int hashindex;
3212         char basename[MAX_QPATH];
3213
3214         Image_StripImageExtension(name, basename, sizeof(basename));
3215
3216         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3217         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3218                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3219                         break;
3220
3221         if (!item) {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 if (!add && !dyntexture)
3226                         return NULL;
3227                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3228                 memset(item, 0, sizeof(*item));
3229                 strlcpy(item->basename, basename, sizeof(item->basename));
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3232                 item->comparewidth = comparewidth;
3233                 item->compareheight = compareheight;
3234                 item->comparecrc = comparecrc;
3235                 item->next = r_skinframe.hash[hashindex];
3236                 r_skinframe.hash[hashindex] = item;
3237         }
3238         else if (textureflags & TEXF_FORCE_RELOAD)
3239         {
3240                 rtexture_t *dyntexture;
3241                 // check whether its a dynamic texture
3242                 dyntexture = CL_GetDynTexture( basename );
3243                 if (!add && !dyntexture)
3244                         return NULL;
3245                 if (item->merged == item->base)
3246                         item->merged = NULL;
3247                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3248                 R_PurgeTexture(item->stain );item->stain  = NULL;
3249                 R_PurgeTexture(item->merged);item->merged = NULL;
3250                 R_PurgeTexture(item->base  );item->base   = NULL;
3251                 R_PurgeTexture(item->pants );item->pants  = NULL;
3252                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3253                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3254                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3255                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3256                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3257         R_PurgeTexture(item->reflect);item->reflect = NULL;
3258                 item->loadsequence = 0;
3259         }
3260         else if( item->base == NULL )
3261         {
3262                 rtexture_t *dyntexture;
3263                 // check whether its a dynamic texture
3264                 // 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]
3265                 dyntexture = CL_GetDynTexture( basename );
3266                 item->base = dyntexture; // either NULL or dyntexture handle
3267         }
3268
3269         R_SkinFrame_MarkUsed(item);
3270         return item;
3271 }
3272
3273 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3274         { \
3275                 unsigned long long avgcolor[5], wsum; \
3276                 int pix, comp, w; \
3277                 avgcolor[0] = 0; \
3278                 avgcolor[1] = 0; \
3279                 avgcolor[2] = 0; \
3280                 avgcolor[3] = 0; \
3281                 avgcolor[4] = 0; \
3282                 wsum = 0; \
3283                 for(pix = 0; pix < cnt; ++pix) \
3284                 { \
3285                         w = 0; \
3286                         for(comp = 0; comp < 3; ++comp) \
3287                                 w += getpixel; \
3288                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3289                         { \
3290                                 ++wsum; \
3291                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3292                                 w = getpixel; \
3293                                 for(comp = 0; comp < 3; ++comp) \
3294                                         avgcolor[comp] += getpixel * w; \
3295                                 avgcolor[3] += w; \
3296                         } \
3297                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3298                         avgcolor[4] += getpixel; \
3299                 } \
3300                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3301                         avgcolor[3] = 1; \
3302                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3303                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3304                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3305                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3306         }
3307
3308 extern cvar_t gl_picmip;
3309 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3310 {
3311         int j;
3312         unsigned char *pixels;
3313         unsigned char *bumppixels;
3314         unsigned char *basepixels = NULL;
3315         int basepixels_width = 0;
3316         int basepixels_height = 0;
3317         skinframe_t *skinframe;
3318         rtexture_t *ddsbase = NULL;
3319         qboolean ddshasalpha = false;
3320         float ddsavgcolor[4];
3321         char basename[MAX_QPATH];
3322         int miplevel = R_PicmipForFlags(textureflags);
3323         int savemiplevel = miplevel;
3324         int mymiplevel;
3325         char vabuf[1024];
3326
3327         if (cls.state == ca_dedicated)
3328                 return NULL;
3329
3330         // return an existing skinframe if already loaded
3331         // if loading of the first image fails, don't make a new skinframe as it
3332         // would cause all future lookups of this to be missing
3333         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3334         if (skinframe && skinframe->base)
3335                 return skinframe;
3336
3337         Image_StripImageExtension(name, basename, sizeof(basename));
3338
3339         // check for DDS texture file first
3340         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3341         {
3342                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3343                 if (basepixels == NULL)
3344                         return NULL;
3345         }
3346
3347         // FIXME handle miplevel
3348
3349         if (developer_loading.integer)
3350                 Con_Printf("loading skin \"%s\"\n", name);
3351
3352         // we've got some pixels to store, so really allocate this new texture now
3353         if (!skinframe)
3354                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3355         textureflags &= ~TEXF_FORCE_RELOAD;
3356         skinframe->stain = NULL;
3357         skinframe->merged = NULL;
3358         skinframe->base = NULL;
3359         skinframe->pants = NULL;
3360         skinframe->shirt = NULL;
3361         skinframe->nmap = NULL;
3362         skinframe->gloss = NULL;
3363         skinframe->glow = NULL;
3364         skinframe->fog = NULL;
3365         skinframe->reflect = NULL;
3366         skinframe->hasalpha = false;
3367
3368         if (ddsbase)
3369         {
3370                 skinframe->base = ddsbase;
3371                 skinframe->hasalpha = ddshasalpha;
3372                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3373                 if (r_loadfog && skinframe->hasalpha)
3374                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3375                 //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]);
3376         }
3377         else
3378         {
3379                 basepixels_width = image_width;
3380                 basepixels_height = image_height;
3381                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3382                 if (textureflags & TEXF_ALPHA)
3383                 {
3384                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3385                         {
3386                                 if (basepixels[j] < 255)
3387                                 {
3388                                         skinframe->hasalpha = true;
3389                                         break;
3390                                 }
3391                         }
3392                         if (r_loadfog && skinframe->hasalpha)
3393                         {
3394                                 // has transparent pixels
3395                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3396                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3397                                 {
3398                                         pixels[j+0] = 255;
3399                                         pixels[j+1] = 255;
3400                                         pixels[j+2] = 255;
3401                                         pixels[j+3] = basepixels[j+3];
3402                                 }
3403                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3404                                 Mem_Free(pixels);
3405                         }
3406                 }
3407                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3408 #ifndef USE_GLES2
3409                 //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]);
3410                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3411                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3413                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         if (r_loaddds)
3418         {
3419                 mymiplevel = savemiplevel;
3420                 if (r_loadnormalmap)
3421                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3422                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 if (r_loadgloss)
3424                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428         }
3429
3430         // _norm is the name used by tenebrae and has been adopted as standard
3431         if (r_loadnormalmap && skinframe->nmap == NULL)
3432         {
3433                 mymiplevel = savemiplevel;
3434                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3435                 {
3436                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3437                         Mem_Free(pixels);
3438                         pixels = NULL;
3439                 }
3440                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3441                 {
3442                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3443                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3444                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3445                         Mem_Free(pixels);
3446                         Mem_Free(bumppixels);
3447                 }
3448                 else if (r_shadow_bumpscale_basetexture.value > 0)
3449                 {
3450                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3451                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3452                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3453                         Mem_Free(pixels);
3454                 }
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3457                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459         }
3460
3461         // _luma is supported only for tenebrae compatibility
3462         // _glow is the preferred name
3463         mymiplevel = savemiplevel;
3464         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3465         {
3466                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3469                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3470 #endif
3471                 Mem_Free(pixels);pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3480                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         mymiplevel = savemiplevel;
3487         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3488         {
3489                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3490 #ifndef USE_GLES2
3491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3492                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3493 #endif
3494                 Mem_Free(pixels);
3495                 pixels = NULL;
3496         }
3497
3498         mymiplevel = savemiplevel;
3499         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3500         {
3501                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3502 #ifndef USE_GLES2
3503                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3504                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3505 #endif
3506                 Mem_Free(pixels);
3507                 pixels = NULL;
3508         }
3509
3510         mymiplevel = savemiplevel;
3511         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3512         {
3513                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3514 #ifndef USE_GLES2
3515                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3516                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3517 #endif
3518                 Mem_Free(pixels);
3519                 pixels = NULL;
3520         }
3521
3522         if (basepixels)
3523                 Mem_Free(basepixels);
3524
3525         return skinframe;
3526 }
3527
3528 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3529 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3530 {
3531         int i;
3532         unsigned char *temp1, *temp2;
3533         skinframe_t *skinframe;
3534         char vabuf[1024];
3535
3536         if (cls.state == ca_dedicated)
3537                 return NULL;
3538
3539         // if already loaded just return it, otherwise make a new skinframe
3540         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3541         if (skinframe->base)
3542                 return skinframe;
3543         textureflags &= ~TEXF_FORCE_RELOAD;
3544
3545         skinframe->stain = NULL;
3546         skinframe->merged = NULL;
3547         skinframe->base = NULL;
3548         skinframe->pants = NULL;
3549         skinframe->shirt = NULL;
3550         skinframe->nmap = NULL;
3551         skinframe->gloss = NULL;
3552         skinframe->glow = NULL;
3553         skinframe->fog = NULL;
3554         skinframe->reflect = NULL;
3555         skinframe->hasalpha = false;
3556
3557         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3558         if (!skindata)
3559                 return NULL;
3560
3561         if (developer_loading.integer)
3562                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3563
3564         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3565         {
3566                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3567                 temp2 = temp1 + width * height * 4;
3568                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3569                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3570                 Mem_Free(temp1);
3571         }
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 3;i < width * height * 4;i += 4)
3576                 {
3577                         if (skindata[i] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                 {
3585                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3586                         memcpy(fogpixels, skindata, width * height * 4);
3587                         for (i = 0;i < width * height * 4;i += 4)
3588                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3589                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3590                         Mem_Free(fogpixels);
3591                 }
3592         }
3593
3594         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3595         //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]);
3596
3597         return skinframe;
3598 }
3599
3600 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3601 {
3602         int i;
3603         int featuresmask;
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         // if already loaded just return it, otherwise make a new skinframe
3610         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3611         if (skinframe->base)
3612                 return skinframe;
3613         //textureflags &= ~TEXF_FORCE_RELOAD;
3614
3615         skinframe->stain = NULL;
3616         skinframe->merged = NULL;
3617         skinframe->base = NULL;
3618         skinframe->pants = NULL;
3619         skinframe->shirt = NULL;
3620         skinframe->nmap = NULL;
3621         skinframe->gloss = NULL;
3622         skinframe->glow = NULL;
3623         skinframe->fog = NULL;
3624         skinframe->reflect = NULL;
3625         skinframe->hasalpha = false;
3626
3627         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3628         if (!skindata)
3629                 return NULL;
3630
3631         if (developer_loading.integer)
3632                 Con_Printf("loading quake skin \"%s\"\n", name);
3633
3634         // 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)
3635         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3636         memcpy(skinframe->qpixels, skindata, width*height);
3637         skinframe->qwidth = width;
3638         skinframe->qheight = height;
3639
3640         featuresmask = 0;
3641         for (i = 0;i < width * height;i++)
3642                 featuresmask |= palette_featureflags[skindata[i]];
3643
3644         skinframe->hasalpha = false;
3645         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3646         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3647         skinframe->qgeneratemerged = true;
3648         skinframe->qgeneratebase = skinframe->qhascolormapping;
3649         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3650
3651         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3652         //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]);
3653
3654         return skinframe;
3655 }
3656
3657 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3658 {
3659         int width;
3660         int height;
3661         unsigned char *skindata;
3662         char vabuf[1024];
3663
3664         if (!skinframe->qpixels)
3665                 return;
3666
3667         if (!skinframe->qhascolormapping)
3668                 colormapped = false;
3669
3670         if (colormapped)
3671         {
3672                 if (!skinframe->qgeneratebase)
3673                         return;
3674         }
3675         else
3676         {
3677                 if (!skinframe->qgeneratemerged)
3678                         return;
3679         }
3680
3681         width = skinframe->qwidth;
3682         height = skinframe->qheight;
3683         skindata = skinframe->qpixels;
3684
3685         if (skinframe->qgeneratenmap)
3686         {
3687                 unsigned char *temp1, *temp2;
3688                 skinframe->qgeneratenmap = false;
3689                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3690                 temp2 = temp1 + width * height * 4;
3691                 // use either a custom palette or the quake palette
3692                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3693                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3694                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3695                 Mem_Free(temp1);
3696         }
3697
3698         if (skinframe->qgenerateglow)
3699         {
3700                 skinframe->qgenerateglow = false;
3701                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3702         }
3703
3704         if (colormapped)
3705         {
3706                 skinframe->qgeneratebase = false;
3707                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3708                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3709                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3710         }
3711         else
3712         {
3713                 skinframe->qgeneratemerged = false;
3714                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3715         }
3716
3717         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3718         {
3719                 Mem_Free(skinframe->qpixels);
3720                 skinframe->qpixels = NULL;
3721         }
3722 }
3723
3724 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)
3725 {
3726         int i;
3727         skinframe_t *skinframe;
3728         char vabuf[1024];
3729
3730         if (cls.state == ca_dedicated)
3731                 return NULL;
3732
3733         // if already loaded just return it, otherwise make a new skinframe
3734         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3735         if (skinframe->base)
3736                 return skinframe;
3737         textureflags &= ~TEXF_FORCE_RELOAD;
3738
3739         skinframe->stain = NULL;
3740         skinframe->merged = NULL;
3741         skinframe->base = NULL;
3742         skinframe->pants = NULL;
3743         skinframe->shirt = NULL;
3744         skinframe->nmap = NULL;
3745         skinframe->gloss = NULL;
3746         skinframe->glow = NULL;
3747         skinframe->fog = NULL;
3748         skinframe->reflect = NULL;
3749         skinframe->hasalpha = false;
3750
3751         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3752         if (!skindata)
3753                 return NULL;
3754
3755         if (developer_loading.integer)
3756                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3757
3758         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3759         if (textureflags & TEXF_ALPHA)
3760         {
3761                 for (i = 0;i < width * height;i++)
3762                 {
3763                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3764                         {
3765                                 skinframe->hasalpha = true;
3766                                 break;
3767                         }
3768                 }
3769                 if (r_loadfog && skinframe->hasalpha)
3770                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3771         }
3772
3773         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3774         //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]);
3775
3776         return skinframe;
3777 }
3778
3779 skinframe_t *R_SkinFrame_LoadMissing(void)
3780 {
3781         skinframe_t *skinframe;
3782
3783         if (cls.state == ca_dedicated)
3784                 return NULL;
3785
3786         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3787         skinframe->stain = NULL;
3788         skinframe->merged = NULL;
3789         skinframe->base = NULL;
3790         skinframe->pants = NULL;
3791         skinframe->shirt = NULL;
3792         skinframe->nmap = NULL;
3793         skinframe->gloss = NULL;
3794         skinframe->glow = NULL;
3795         skinframe->fog = NULL;
3796         skinframe->reflect = NULL;
3797         skinframe->hasalpha = false;
3798
3799         skinframe->avgcolor[0] = rand() / RAND_MAX;
3800         skinframe->avgcolor[1] = rand() / RAND_MAX;
3801         skinframe->avgcolor[2] = rand() / RAND_MAX;
3802         skinframe->avgcolor[3] = 1;
3803
3804         return skinframe;
3805 }
3806
3807 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3808 typedef struct suffixinfo_s
3809 {
3810         const char *suffix;
3811         qboolean flipx, flipy, flipdiagonal;
3812 }
3813 suffixinfo_t;
3814 static suffixinfo_t suffix[3][6] =
3815 {
3816         {
3817                 {"px",   false, false, false},
3818                 {"nx",   false, false, false},
3819                 {"py",   false, false, false},
3820                 {"ny",   false, false, false},
3821                 {"pz",   false, false, false},
3822                 {"nz",   false, false, false}
3823         },
3824         {
3825                 {"posx", false, false, false},
3826                 {"negx", false, false, false},
3827                 {"posy", false, false, false},
3828                 {"negy", false, false, false},
3829                 {"posz", false, false, false},
3830                 {"negz", false, false, false}
3831         },
3832         {
3833                 {"rt",    true, false,  true},
3834                 {"lf",   false,  true,  true},
3835                 {"ft",    true,  true, false},
3836                 {"bk",   false, false, false},
3837                 {"up",    true, false,  true},
3838                 {"dn",    true, false,  true}
3839         }
3840 };
3841
3842 static int componentorder[4] = {0, 1, 2, 3};
3843
3844 static rtexture_t *R_LoadCubemap(const char *basename)
3845 {
3846         int i, j, cubemapsize;
3847         unsigned char *cubemappixels, *image_buffer;
3848         rtexture_t *cubemaptexture;
3849         char name[256];
3850         // must start 0 so the first loadimagepixels has no requested width/height
3851         cubemapsize = 0;
3852         cubemappixels = NULL;
3853         cubemaptexture = NULL;
3854         // keep trying different suffix groups (posx, px, rt) until one loads
3855         for (j = 0;j < 3 && !cubemappixels;j++)
3856         {
3857                 // load the 6 images in the suffix group
3858                 for (i = 0;i < 6;i++)
3859                 {
3860                         // generate an image name based on the base and and suffix
3861                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3862                         // load it
3863                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3864                         {
3865                                 // an image loaded, make sure width and height are equal
3866                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3867                                 {
3868                                         // if this is the first image to load successfully, allocate the cubemap memory
3869                                         if (!cubemappixels && image_width >= 1)
3870                                         {
3871                                                 cubemapsize = image_width;
3872                                                 // note this clears to black, so unavailable sides are black
3873                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3874                                         }
3875                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3876                                         if (cubemappixels)
3877                                                 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);
3878                                 }
3879                                 else
3880                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3881                                 // free the image
3882                                 Mem_Free(image_buffer);
3883                         }
3884                 }
3885         }
3886         // if a cubemap loaded, upload it
3887         if (cubemappixels)
3888         {
3889                 if (developer_loading.integer)
3890                         Con_Printf("loading cubemap \"%s\"\n", basename);
3891
3892                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3893                 Mem_Free(cubemappixels);
3894         }
3895         else
3896         {
3897                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3898                 if (developer_loading.integer)
3899                 {
3900                         Con_Printf("(tried tried images ");
3901                         for (j = 0;j < 3;j++)
3902                                 for (i = 0;i < 6;i++)
3903                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3904                         Con_Print(" and was unable to find any of them).\n");
3905                 }
3906         }
3907         return cubemaptexture;
3908 }
3909
3910 rtexture_t *R_GetCubemap(const char *basename)
3911 {
3912         int i;
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914                 if (r_texture_cubemaps[i] != NULL)
3915                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3916                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3917         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3918                 return r_texture_whitecube;
3919         r_texture_numcubemaps++;
3920         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3921         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3922         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3923         return r_texture_cubemaps[i]->texture;
3924 }
3925
3926 static void R_Main_FreeViewCache(void)
3927 {
3928         if (r_refdef.viewcache.entityvisible)
3929                 Mem_Free(r_refdef.viewcache.entityvisible);
3930         if (r_refdef.viewcache.world_pvsbits)
3931                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3932         if (r_refdef.viewcache.world_leafvisible)
3933                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3934         if (r_refdef.viewcache.world_surfacevisible)
3935                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3937 }
3938
3939 static void R_Main_ResizeViewCache(void)
3940 {
3941         int numentities = r_refdef.scene.numentities;
3942         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3943         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3944         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3945         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3946         if (r_refdef.viewcache.maxentities < numentities)
3947         {
3948                 r_refdef.viewcache.maxentities = numentities;
3949                 if (r_refdef.viewcache.entityvisible)
3950                         Mem_Free(r_refdef.viewcache.entityvisible);
3951                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952         }
3953         if (r_refdef.viewcache.world_numclusters != numclusters)
3954         {
3955                 r_refdef.viewcache.world_numclusters = numclusters;
3956                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3957                 if (r_refdef.viewcache.world_pvsbits)
3958                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3959                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960         }
3961         if (r_refdef.viewcache.world_numleafs != numleafs)
3962         {
3963                 r_refdef.viewcache.world_numleafs = numleafs;
3964                 if (r_refdef.viewcache.world_leafvisible)
3965                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3966                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967         }
3968         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969         {
3970                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3971                 if (r_refdef.viewcache.world_surfacevisible)
3972                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974         }
3975 }
3976
3977 extern rtexture_t *loadingscreentexture;
3978 static void gl_main_start(void)
3979 {
3980         loadingscreentexture = NULL;
3981         r_texture_blanknormalmap = NULL;
3982         r_texture_white = NULL;
3983         r_texture_grey128 = NULL;
3984         r_texture_black = NULL;
3985         r_texture_whitecube = NULL;
3986         r_texture_normalizationcube = NULL;
3987         r_texture_fogattenuation = NULL;
3988         r_texture_fogheighttexture = NULL;
3989         r_texture_gammaramps = NULL;
3990         r_texture_numcubemaps = 0;
3991         r_uniformbufferalignment = 32;
3992
3993         r_loaddds = r_texture_dds_load.integer != 0;
3994         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995
3996         switch(vid.renderpath)
3997         {
3998         case RENDERPATH_GL20:
3999         case RENDERPATH_D3D9:
4000         case RENDERPATH_D3D10:
4001         case RENDERPATH_D3D11:
4002         case RENDERPATH_SOFT:
4003         case RENDERPATH_GLES2:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 1);
4007                 r_loadnormalmap = true;
4008                 r_loadgloss = true;
4009                 r_loadfog = false;
4010                 if (vid.support.arb_uniform_buffer_object)
4011                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012                 break;
4013         case RENDERPATH_GL13:
4014         case RENDERPATH_GLES1:
4015                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016                 Cvar_SetValueQuick(&gl_combine, 1);
4017                 Cvar_SetValueQuick(&r_glsl, 0);
4018                 r_loadnormalmap = false;
4019                 r_loadgloss = false;
4020                 r_loadfog = true;
4021                 break;
4022         case RENDERPATH_GL11:
4023                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4024                 Cvar_SetValueQuick(&gl_combine, 0);
4025                 Cvar_SetValueQuick(&r_glsl, 0);
4026                 r_loadnormalmap = false;
4027                 r_loadgloss = false;
4028                 r_loadfog = true;
4029                 break;
4030         }
4031
4032         R_AnimCache_Free();
4033         R_FrameData_Reset();
4034         R_BufferData_Reset();
4035
4036         r_numqueries = 0;
4037         r_maxqueries = 0;
4038         memset(r_queries, 0, sizeof(r_queries));
4039
4040         r_qwskincache = NULL;
4041         r_qwskincache_size = 0;
4042
4043         // due to caching of texture_t references, the collision cache must be reset
4044         Collision_Cache_Reset(true);
4045
4046         // set up r_skinframe loading system for textures
4047         memset(&r_skinframe, 0, sizeof(r_skinframe));
4048         r_skinframe.loadsequence = 1;
4049         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4050
4051         r_main_texturepool = R_AllocTexturePool();
4052         R_BuildBlankTextures();
4053         R_BuildNoTexture();
4054         if (vid.support.arb_texture_cube_map)
4055         {
4056                 R_BuildWhiteCube();
4057                 R_BuildNormalizationCube();
4058         }
4059         r_texture_fogattenuation = NULL;
4060         r_texture_fogheighttexture = NULL;
4061         r_texture_gammaramps = NULL;
4062         //r_texture_fogintensity = NULL;
4063         memset(&r_fb, 0, sizeof(r_fb));
4064         r_glsl_permutation = NULL;
4065         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4067         glslshaderstring = NULL;
4068 #ifdef SUPPORTD3D
4069         r_hlsl_permutation = NULL;
4070         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4071         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4072 #endif
4073         hlslshaderstring = NULL;
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075
4076         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077         r_texture_numcubemaps = 0;
4078
4079         r_refdef.fogmasktable_density = 0;
4080 }
4081
4082 static void gl_main_shutdown(void)
4083 {
4084         R_AnimCache_Free();
4085         R_FrameData_Reset();
4086         R_BufferData_Reset();
4087
4088         R_Main_FreeViewCache();
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL11:
4093         case RENDERPATH_GL13:
4094         case RENDERPATH_GL20:
4095         case RENDERPATH_GLES1:
4096         case RENDERPATH_GLES2:
4097 #ifdef GL_SAMPLES_PASSED_ARB
4098                 if (r_maxqueries)
4099                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4100 #endif
4101                 break;
4102         case RENDERPATH_D3D9:
4103                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D10:
4106                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_D3D11:
4109                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4110                 break;
4111         case RENDERPATH_SOFT:
4112                 break;
4113         }
4114
4115         r_numqueries = 0;
4116         r_maxqueries = 0;
4117         memset(r_queries, 0, sizeof(r_queries));
4118
4119         r_qwskincache = NULL;
4120         r_qwskincache_size = 0;
4121
4122         // clear out the r_skinframe state
4123         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4124         memset(&r_skinframe, 0, sizeof(r_skinframe));
4125
4126         if (r_svbsp.nodes)
4127                 Mem_Free(r_svbsp.nodes);
4128         memset(&r_svbsp, 0, sizeof (r_svbsp));
4129         R_FreeTexturePool(&r_main_texturepool);
4130         loadingscreentexture = NULL;
4131         r_texture_blanknormalmap = NULL;
4132         r_texture_white = NULL;
4133         r_texture_grey128 = NULL;
4134         r_texture_black = NULL;
4135         r_texture_whitecube = NULL;
4136         r_texture_normalizationcube = NULL;
4137         r_texture_fogattenuation = NULL;
4138         r_texture_fogheighttexture = NULL;
4139         r_texture_gammaramps = NULL;
4140         r_texture_numcubemaps = 0;
4141         //r_texture_fogintensity = NULL;
4142         memset(&r_fb, 0, sizeof(r_fb));
4143         R_GLSL_Restart_f();
4144
4145         r_glsl_permutation = NULL;
4146         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4147         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4148         glslshaderstring = NULL;
4149 #ifdef SUPPORTD3D
4150         r_hlsl_permutation = NULL;
4151         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4152         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4153 #endif
4154         hlslshaderstring = NULL;
4155 }
4156
4157 static void gl_main_newmap(void)
4158 {
4159         // FIXME: move this code to client
4160         char *entities, entname[MAX_QPATH];
4161         if (r_qwskincache)
4162                 Mem_Free(r_qwskincache);
4163         r_qwskincache = NULL;
4164         r_qwskincache_size = 0;
4165         if (cl.worldmodel)
4166         {
4167                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4168                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4169                 {
4170                         CL_ParseEntityLump(entities);
4171                         Mem_Free(entities);
4172                         return;
4173                 }
4174                 if (cl.worldmodel->brush.entities)
4175                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4176         }
4177         R_Main_FreeViewCache();
4178
4179         R_FrameData_Reset();
4180         R_BufferData_Reset();
4181 }
4182
4183 void GL_Main_Init(void)
4184 {
4185         int i;
4186         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4187
4188         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4189         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4190         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4191         if (gamemode == GAME_NEHAHRA)
4192         {
4193                 Cvar_RegisterVariable (&gl_fogenable);
4194                 Cvar_RegisterVariable (&gl_fogdensity);
4195                 Cvar_RegisterVariable (&gl_fogred);
4196                 Cvar_RegisterVariable (&gl_foggreen);
4197                 Cvar_RegisterVariable (&gl_fogblue);
4198                 Cvar_RegisterVariable (&gl_fogstart);
4199                 Cvar_RegisterVariable (&gl_fogend);
4200                 Cvar_RegisterVariable (&gl_skyclip);
4201         }
4202         Cvar_RegisterVariable(&r_motionblur);
4203         Cvar_RegisterVariable(&r_damageblur);
4204         Cvar_RegisterVariable(&r_motionblur_averaging);
4205         Cvar_RegisterVariable(&r_motionblur_randomize);
4206         Cvar_RegisterVariable(&r_motionblur_minblur);
4207         Cvar_RegisterVariable(&r_motionblur_maxblur);
4208         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4209         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4211         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4212         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4213         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4214         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4215         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4216         Cvar_RegisterVariable(&r_equalize_entities_by);
4217         Cvar_RegisterVariable(&r_equalize_entities_to);
4218         Cvar_RegisterVariable(&r_depthfirst);
4219         Cvar_RegisterVariable(&r_useinfinitefarclip);
4220         Cvar_RegisterVariable(&r_farclip_base);
4221         Cvar_RegisterVariable(&r_farclip_world);
4222         Cvar_RegisterVariable(&r_nearclip);
4223         Cvar_RegisterVariable(&r_deformvertexes);
4224         Cvar_RegisterVariable(&r_transparent);
4225         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4226         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4227         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4228         Cvar_RegisterVariable(&r_showoverdraw);
4229         Cvar_RegisterVariable(&r_showbboxes);
4230         Cvar_RegisterVariable(&r_showsurfaces);
4231         Cvar_RegisterVariable(&r_showtris);
4232         Cvar_RegisterVariable(&r_shownormals);
4233         Cvar_RegisterVariable(&r_showlighting);
4234         Cvar_RegisterVariable(&r_showshadowvolumes);
4235         Cvar_RegisterVariable(&r_showcollisionbrushes);
4236         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4237         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4238         Cvar_RegisterVariable(&r_showdisabledepthtest);
4239         Cvar_RegisterVariable(&r_drawportals);
4240         Cvar_RegisterVariable(&r_drawentities);
4241         Cvar_RegisterVariable(&r_draw2d);
4242         Cvar_RegisterVariable(&r_drawworld);
4243         Cvar_RegisterVariable(&r_cullentities_trace);
4244         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4245         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4246         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4247         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4248         Cvar_RegisterVariable(&r_sortentities);
4249         Cvar_RegisterVariable(&r_drawviewmodel);
4250         Cvar_RegisterVariable(&r_drawexteriormodel);
4251         Cvar_RegisterVariable(&r_speeds);
4252         Cvar_RegisterVariable(&r_fullbrights);
4253         Cvar_RegisterVariable(&r_wateralpha);
4254         Cvar_RegisterVariable(&r_dynamic);
4255         Cvar_RegisterVariable(&r_fakelight);
4256         Cvar_RegisterVariable(&r_fakelight_intensity);
4257         Cvar_RegisterVariable(&r_fullbright);
4258         Cvar_RegisterVariable(&r_shadows);
4259         Cvar_RegisterVariable(&r_shadows_darken);
4260         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4261         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4262         Cvar_RegisterVariable(&r_shadows_throwdistance);
4263         Cvar_RegisterVariable(&r_shadows_throwdirection);
4264         Cvar_RegisterVariable(&r_shadows_focus);
4265         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4267         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4268         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4270         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4272         Cvar_RegisterVariable(&r_fog_exp2);
4273         Cvar_RegisterVariable(&r_fog_clear);
4274         Cvar_RegisterVariable(&r_drawfog);
4275         Cvar_RegisterVariable(&r_transparentdepthmasking);
4276         Cvar_RegisterVariable(&r_transparent_sortmindist);
4277         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4278         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4279         Cvar_RegisterVariable(&r_texture_dds_load);
4280         Cvar_RegisterVariable(&r_texture_dds_save);
4281         Cvar_RegisterVariable(&r_textureunits);
4282         Cvar_RegisterVariable(&gl_combine);
4283         Cvar_RegisterVariable(&r_usedepthtextures);
4284         Cvar_RegisterVariable(&r_viewfbo);
4285         Cvar_RegisterVariable(&r_viewscale);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4292         Cvar_RegisterVariable(&r_glsl);
4293         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4302         Cvar_RegisterVariable(&r_glsl_postprocess);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4311         Cvar_RegisterVariable(&r_celshading);
4312         Cvar_RegisterVariable(&r_celoutlines);
4313
4314         Cvar_RegisterVariable(&r_water);
4315         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4316         Cvar_RegisterVariable(&r_water_clippingplanebias);
4317         Cvar_RegisterVariable(&r_water_refractdistort);
4318         Cvar_RegisterVariable(&r_water_reflectdistort);
4319         Cvar_RegisterVariable(&r_water_scissormode);
4320         Cvar_RegisterVariable(&r_water_lowquality);
4321         Cvar_RegisterVariable(&r_water_hideplayer);
4322         Cvar_RegisterVariable(&r_water_fbo);
4323
4324         Cvar_RegisterVariable(&r_lerpsprites);
4325         Cvar_RegisterVariable(&r_lerpmodels);
4326         Cvar_RegisterVariable(&r_lerplightstyles);
4327         Cvar_RegisterVariable(&r_waterscroll);
4328         Cvar_RegisterVariable(&r_bloom);
4329         Cvar_RegisterVariable(&r_bloom_colorscale);
4330         Cvar_RegisterVariable(&r_bloom_brighten);
4331         Cvar_RegisterVariable(&r_bloom_blur);
4332         Cvar_RegisterVariable(&r_bloom_resolution);
4333         Cvar_RegisterVariable(&r_bloom_colorexponent);
4334         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4335         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4336         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4337         Cvar_RegisterVariable(&r_hdr_glowintensity);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4346         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4347         Cvar_RegisterVariable(&developer_texturelogging);
4348         Cvar_RegisterVariable(&gl_lightmaps);
4349         Cvar_RegisterVariable(&r_test);
4350         Cvar_RegisterVariable(&r_batch_multidraw);
4351         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4352         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4353         Cvar_RegisterVariable(&r_glsl_skeletal);
4354         Cvar_RegisterVariable(&r_glsl_saturation);
4355         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4356         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4357         Cvar_RegisterVariable(&r_framedatasize);
4358         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4359                 Cvar_RegisterVariable(&r_bufferdatasize[i]);
4360         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4361         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4362                 Cvar_SetValue("r_fullbrights", 0);
4363         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4364 }
4365
4366 void Render_Init(void)
4367 {
4368         gl_backend_init();
4369         R_Textures_Init();
4370         GL_Main_Init();
4371         Font_Init();
4372         GL_Draw_Init();
4373         R_Shadow_Init();
4374         R_Sky_Init();
4375         GL_Surf_Init();
4376         Sbar_Init();
4377         R_Particles_Init();
4378         R_Explosion_Init();
4379         R_LightningBeams_Init();
4380         Mod_RenderInit();
4381 }
4382
4383 /*
4384 ===============
4385 GL_Init
4386 ===============
4387 */
4388 #ifndef USE_GLES2
4389 extern char *ENGINE_EXTENSIONS;
4390 void GL_Init (void)
4391 {
4392         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4393         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4394         gl_version = (const char *)qglGetString(GL_VERSION);
4395         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4396
4397         if (!gl_extensions)
4398                 gl_extensions = "";
4399         if (!gl_platformextensions)
4400                 gl_platformextensions = "";
4401
4402         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4403         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4404         Con_Printf("GL_VERSION: %s\n", gl_version);
4405         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4406         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4407
4408         VID_CheckExtensions();
4409
4410         // LordHavoc: report supported extensions
4411         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4412
4413         // clear to black (loading plaque will be seen over this)
4414         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4415 }
4416 #endif
4417
4418 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4419 {
4420         int i;
4421         mplane_t *p;
4422         if (r_trippy.integer)
4423                 return false;
4424         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4425         {
4426                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4427                 if (i == 4)
4428                         continue;
4429                 p = r_refdef.view.frustum + i;
4430                 switch(p->signbits)
4431                 {
4432                 default:
4433                 case 0:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 1:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 2:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 3:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 4:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 5:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 6:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 7:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 }
4466         }
4467         return false;
4468 }
4469
4470 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4471 {
4472         int i;
4473         const mplane_t *p;
4474         if (r_trippy.integer)
4475                 return false;
4476         for (i = 0;i < numplanes;i++)
4477         {
4478                 p = planes + i;
4479                 switch(p->signbits)
4480                 {
4481                 default:
4482                 case 0:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 1:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 2:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 3:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 4:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 5:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 6:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 7:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 }
4515         }
4516         return false;
4517 }
4518
4519 //==================================================================================
4520
4521 // LordHavoc: this stores temporary data used within the same frame
4522
4523 typedef struct r_framedata_mem_s
4524 {
4525         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4526         size_t size; // how much usable space
4527         size_t current; // how much space in use
4528         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4529         size_t wantedsize; // how much space was allocated
4530         unsigned char *data; // start of real data (16byte aligned)
4531 }
4532 r_framedata_mem_t;
4533
4534 static r_framedata_mem_t *r_framedata_mem;
4535
4536 void R_FrameData_Reset(void)
4537 {
4538         while (r_framedata_mem)
4539         {
4540                 r_framedata_mem_t *next = r_framedata_mem->purge;
4541                 Mem_Free(r_framedata_mem);
4542                 r_framedata_mem = next;
4543         }
4544 }
4545
4546 static void R_FrameData_Resize(qboolean mustgrow)
4547 {
4548         size_t wantedsize;
4549         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4550         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4551         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4552         {
4553                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4554                 newmem->wantedsize = wantedsize;
4555                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4556                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4557                 newmem->current = 0;
4558                 newmem->mark = 0;
4559                 newmem->purge = r_framedata_mem;
4560                 r_framedata_mem = newmem;
4561         }
4562 }
4563
4564 void R_FrameData_NewFrame(void)
4565 {
4566         R_FrameData_Resize(false);
4567         if (!r_framedata_mem)
4568                 return;
4569         // if we ran out of space on the last frame, free the old memory now
4570         while (r_framedata_mem->purge)
4571         {
4572                 // repeatedly remove the second item in the list, leaving only head
4573                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4574                 Mem_Free(r_framedata_mem->purge);
4575                 r_framedata_mem->purge = next;
4576         }
4577         // reset the current mem pointer
4578         r_framedata_mem->current = 0;
4579         r_framedata_mem->mark = 0;
4580 }
4581
4582 void *R_FrameData_Alloc(size_t size)
4583 {
4584         void *data;
4585         float newvalue;
4586
4587         // align to 16 byte boundary - the data pointer is already aligned, so we
4588         // only need to ensure the size of every allocation is also aligned
4589         size = (size + 15) & ~15;
4590
4591         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4592         {
4593                 // emergency - we ran out of space, allocate more memory
4594                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4595                 // this might not be a growing it, but we'll allocate another buffer every time
4596                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4597                 R_FrameData_Resize(true);
4598         }
4599
4600         data = r_framedata_mem->data + r_framedata_mem->current;
4601         r_framedata_mem->current += size;
4602
4603         // count the usage for stats
4604         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4605         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4606
4607         return (void *)data;
4608 }
4609
4610 void *R_FrameData_Store(size_t size, void *data)
4611 {
4612         void *d = R_FrameData_Alloc(size);
4613         if (d && data)
4614                 memcpy(d, data, size);
4615         return d;
4616 }
4617
4618 void R_FrameData_SetMark(void)
4619 {
4620         if (!r_framedata_mem)
4621                 return;
4622         r_framedata_mem->mark = r_framedata_mem->current;
4623 }
4624
4625 void R_FrameData_ReturnToMark(void)
4626 {
4627         if (!r_framedata_mem)
4628                 return;
4629         r_framedata_mem->current = r_framedata_mem->mark;
4630 }
4631
4632 //==================================================================================
4633
4634 // avoid reusing the same buffer objects on consecutive buffers
4635 #define R_BUFFERDATA_CYCLE 2
4636
4637 typedef struct r_bufferdata_buffer_s
4638 {
4639         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4640         size_t size; // how much usable space
4641         size_t current; // how much space in use
4642         r_meshbuffer_t *buffer; // the buffer itself
4643 }
4644 r_bufferdata_buffer_t;
4645
4646 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4647 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4648
4649 /// frees all dynamic buffers
4650 void R_BufferData_Reset(void)
4651 {
4652         int cycle, type;
4653         r_bufferdata_buffer_t **p, *mem;
4654         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4655         {
4656                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4657                 {
4658                         // free all buffers
4659                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
4660                         while (*p)
4661                         {
4662                                 mem = *p;
4663                                 *p = (*p)->purge;
4664                                 if (mem->buffer)
4665                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4666                                 Mem_Free(mem);
4667                         }
4668                 }
4669         }
4670 }
4671
4672 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4673 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
4674 {
4675         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4676         size_t size;
4677         size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
4678         size = bound(65536, size, 512*1024*1024);
4679         if (!mem || mem->size != size || mustgrow)
4680         {
4681                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4682                 mem->size = size;
4683                 mem->current = 0;
4684                 if (type == R_BUFFERDATA_VERTEX)
4685                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4686                 else if (type == R_BUFFERDATA_INDEX16)
4687                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4688                 else if (type == R_BUFFERDATA_INDEX32)
4689                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4690                 else if (type == R_BUFFERDATA_UNIFORM)
4691                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4692                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4693                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4694         }
4695 }
4696
4697 void R_BufferData_NewFrame(void)
4698 {
4699         int type;
4700         r_bufferdata_buffer_t **p, *mem;
4701         // cycle to the next frame's buffers
4702         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4703         // if we ran out of space on the last time we used these buffers, free the old memory now
4704         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4705         {
4706                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4707                 {
4708                         R_BufferData_Resize((r_bufferdata_type_t)type, false);
4709                         // free all but the head buffer, this is how we recycle obsolete
4710                         // buffers after they are no longer in use
4711                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4712                         while (*p)
4713                         {
4714                                 mem = *p;
4715                                 *p = (*p)->purge;
4716                                 if (mem->buffer)
4717                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4718                                 Mem_Free(mem);
4719                         }
4720                         // reset the current offset
4721                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4722                 }
4723         }
4724 }
4725
4726 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
4727 {
4728         r_bufferdata_buffer_t *mem;
4729         int offset = 0;
4730         int padsize;
4731         float newvalue;
4732
4733         *returnbufferoffset = 0;
4734
4735         // align size to a byte boundary appropriate for the buffer type, this
4736         // makes all allocations have aligned start offsets
4737         if (type == R_BUFFERDATA_UNIFORM)
4738                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4739         else
4740                 padsize = (datasize + 15) & ~15;
4741
4742         while (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4743         {
4744                 // emergency - we ran out of space, allocate more memory
4745                 newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
4746                 // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
4747                 if (newvalue == r_bufferdatasize[type].value && allowfail)
4748                         return NULL;
4749                 Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
4750                 R_BufferData_Resize(type, true);
4751         }
4752
4753         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4754         offset = mem->current;
4755         mem->current += padsize;
4756
4757         // upload the data to the buffer at the chosen offset
4758         if (offset == 0)
4759                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4760         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4761
4762         // count the usage for stats
4763         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4764         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4765
4766         // return the buffer offset
4767         *returnbufferoffset = offset;
4768
4769         return mem->buffer;
4770 }
4771
4772 //==================================================================================
4773
4774 // LordHavoc: animcache originally written by Echon, rewritten since then
4775
4776 /**
4777  * Animation cache prevents re-generating mesh data for an animated model
4778  * multiple times in one frame for lighting, shadowing, reflections, etc.
4779  */
4780
4781 void R_AnimCache_Free(void)
4782 {
4783 }
4784
4785 void R_AnimCache_ClearCache(void)
4786 {
4787         int i;
4788         entity_render_t *ent;
4789
4790         for (i = 0;i < r_refdef.scene.numentities;i++)
4791         {
4792                 ent = r_refdef.scene.entities[i];
4793                 ent->animcache_vertex3f = NULL;
4794                 ent->animcache_vertex3f_vertexbuffer = NULL;
4795                 ent->animcache_vertex3f_bufferoffset = 0;
4796                 ent->animcache_normal3f = NULL;
4797                 ent->animcache_normal3f_vertexbuffer = NULL;
4798                 ent->animcache_normal3f_bufferoffset = 0;
4799                 ent->animcache_svector3f = NULL;
4800                 ent->animcache_svector3f_vertexbuffer = NULL;
4801                 ent->animcache_svector3f_bufferoffset = 0;
4802                 ent->animcache_tvector3f = NULL;
4803                 ent->animcache_tvector3f_vertexbuffer = NULL;
4804                 ent->animcache_tvector3f_bufferoffset = 0;
4805                 ent->animcache_vertexmesh = NULL;
4806                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4807                 ent->animcache_vertexmesh_bufferoffset = 0;
4808                 ent->animcache_skeletaltransform3x4 = NULL;
4809                 ent->animcache_skeletaltransform3x4buffer = NULL;
4810                 ent->animcache_skeletaltransform3x4offset = 0;
4811                 ent->animcache_skeletaltransform3x4size = 0;
4812         }
4813 }
4814
4815 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4816 {
4817         int i;
4818
4819         // check if we need the meshbuffers
4820         if (!vid.useinterleavedarrays)
4821                 return;
4822
4823         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4824                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4825         // TODO: upload vertexbuffer?
4826         if (ent->animcache_vertexmesh)
4827         {
4828                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4829                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4830                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4831                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4832                 for (i = 0;i < numvertices;i++)
4833                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4834                 if (ent->animcache_svector3f)
4835                         for (i = 0;i < numvertices;i++)
4836                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4837                 if (ent->animcache_tvector3f)
4838                         for (i = 0;i < numvertices;i++)
4839                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4840                 if (ent->animcache_normal3f)
4841                         for (i = 0;i < numvertices;i++)
4842                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4843         }
4844 }
4845
4846 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4847 {
4848         dp_model_t *model = ent->model;
4849         int numvertices;
4850
4851         // see if this ent is worth caching
4852         if (!model || !model->Draw || !model->AnimateVertices)
4853                 return false;
4854         // nothing to cache if it contains no animations and has no skeleton
4855         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4856                 return false;
4857         // see if it is already cached for gpuskeletal
4858         if (ent->animcache_skeletaltransform3x4)
4859                 return false;
4860         // see if it is already cached as a mesh
4861         if (ent->animcache_vertex3f)
4862         {
4863                 // check if we need to add normals or tangents
4864                 if (ent->animcache_normal3f)
4865                         wantnormals = false;
4866                 if (ent->animcache_svector3f)
4867                         wanttangents = false;
4868                 if (!wantnormals && !wanttangents)
4869                         return false;
4870         }
4871
4872         // check which kind of cache we need to generate
4873         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4874         {
4875                 // cache the skeleton so the vertex shader can use it
4876                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4877                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4878                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4879                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4880                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4881                 // note: this can fail if the buffer is at the grow limit
4882                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4883                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
4884         }
4885         else if (ent->animcache_vertex3f)
4886         {
4887                 // mesh was already cached but we may need to add normals/tangents
4888                 // (this only happens with multiple views, reflections, cameras, etc)
4889                 if (wantnormals || wanttangents)
4890                 {
4891                         numvertices = model->surfmesh.num_vertices;
4892                         if (wantnormals)
4893                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4894                         if (wanttangents)
4895                         {
4896                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4897                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4898                         }
4899                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4900                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4901                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4902                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4903                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4904                 }
4905         }
4906         else
4907         {
4908                 // generate mesh cache
4909                 numvertices = model->surfmesh.num_vertices;
4910                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4911                 if (wantnormals)
4912                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4913                 if (wanttangents)
4914                 {
4915                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4916                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4917                 }
4918                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4919                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4920                 if (wantnormals || wanttangents)
4921                 {
4922                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4923                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4924                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4925                 }
4926                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4927                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4928                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4929         }
4930         return true;
4931 }
4932
4933 void R_AnimCache_CacheVisibleEntities(void)
4934 {
4935         int i;
4936         qboolean wantnormals = true;
4937         qboolean wanttangents = !r_showsurfaces.integer;
4938
4939         switch(vid.renderpath)
4940         {
4941         case RENDERPATH_GL20:
4942         case RENDERPATH_D3D9:
4943         case RENDERPATH_D3D10:
4944         case RENDERPATH_D3D11:
4945         case RENDERPATH_GLES2:
4946                 break;
4947         case RENDERPATH_GL11:
4948         case RENDERPATH_GL13:
4949         case RENDERPATH_GLES1:
4950                 wanttangents = false;
4951                 break;
4952         case RENDERPATH_SOFT:
4953                 break;
4954         }
4955
4956         if (r_shownormals.integer)
4957                 wanttangents = wantnormals = true;
4958
4959         // TODO: thread this
4960         // NOTE: R_PrepareRTLights() also caches entities
4961
4962         for (i = 0;i < r_refdef.scene.numentities;i++)
4963                 if (r_refdef.viewcache.entityvisible[i])
4964                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4965 }
4966
4967 //==================================================================================
4968
4969 extern cvar_t r_overheadsprites_pushback;
4970
4971 static void R_View_UpdateEntityLighting (void)
4972 {
4973         int i;
4974         entity_render_t *ent;
4975         vec3_t tempdiffusenormal, avg;
4976         vec_t f, fa, fd, fdd;
4977         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4978
4979         for (i = 0;i < r_refdef.scene.numentities;i++)
4980         {
4981                 ent = r_refdef.scene.entities[i];
4982
4983                 // skip unseen models
4984                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4985                         continue;
4986
4987                 // skip bsp models
4988                 if (ent->model && ent->model == cl.worldmodel)
4989                 {
4990                         // TODO: use modellight for r_ambient settings on world?
4991                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4992                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4993                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4994                         continue;
4995                 }
4996                 
4997                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4998                 {
4999                         // aleady updated by CSQC
5000                         // TODO: force modellight on BSP models in this case?
5001                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5002                 }
5003                 else
5004                 {
5005                         // fetch the lighting from the worldmodel data
5006                         VectorClear(ent->modellight_ambient);
5007                         VectorClear(ent->modellight_diffuse);
5008                         VectorClear(tempdiffusenormal);
5009                         if (ent->flags & RENDER_LIGHT)
5010                         {
5011                                 vec3_t org;
5012                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5013
5014                                 // complete lightning for lit sprites
5015                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5016                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5017                                 {
5018                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5019                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5020                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5021                                 }
5022                                 else
5023                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5024
5025                                 if(ent->flags & RENDER_EQUALIZE)
5026                                 {
5027                                         // first fix up ambient lighting...
5028                                         if(r_equalize_entities_minambient.value > 0)
5029                                         {
5030                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5031                                                 if(fd > 0)
5032                                                 {
5033                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5034                                                         if(fa < r_equalize_entities_minambient.value * fd)
5035                                                         {
5036                                                                 // solve:
5037                                                                 //   fa'/fd' = minambient
5038                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5039                                                                 //   ...
5040                                                                 //   fa' = fd' * minambient
5041                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5042                                                                 //   ...
5043                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5044                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5045                                                                 //   ...
5046                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5047                                                                 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
5048                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5049                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5050                                                         }
5051                                                 }
5052                                         }
5053
5054                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5055                                         {
5056                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5057                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5058                                                 f = fa + 0.25 * fd;
5059                                                 if(f > 0)
5060                                                 {
5061                                                         // adjust brightness and saturation to target
5062                                                         avg[0] = avg[1] = avg[2] = fa / f;
5063                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5064                                                         avg[0] = avg[1] = avg[2] = fd / f;
5065                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5066                                                 }
5067                                         }
5068                                 }
5069                         }
5070                         else // highly rare
5071                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5072                 }
5073
5074                 // move the light direction into modelspace coordinates for lighting code
5075                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5076                 if(VectorLength2(ent->modellight_lightdir) == 0)
5077                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5078                 VectorNormalize(ent->modellight_lightdir);
5079         }
5080 }
5081
5082 #define MAX_LINEOFSIGHTTRACES 64
5083
5084 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5085 {
5086         int i;
5087         vec3_t boxmins, boxmaxs;
5088         vec3_t start;
5089         vec3_t end;
5090         dp_model_t *model = r_refdef.scene.worldmodel;
5091
5092         if (!model || !model->brush.TraceLineOfSight)
5093                 return true;
5094
5095         // expand the box a little
5096         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5097         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5098         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5099         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5100         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5101         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5102
5103         // return true if eye is inside enlarged box
5104         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5105                 return true;
5106
5107         // try center
5108         VectorCopy(eye, start);
5109         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5110         if (model->brush.TraceLineOfSight(model, start, end))
5111                 return true;
5112
5113         // try various random positions
5114         for (i = 0;i < numsamples;i++)
5115         {
5116                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5117                 if (model->brush.TraceLineOfSight(model, start, end))
5118                         return true;
5119         }
5120
5121         return false;
5122 }
5123
5124
5125 static void R_View_UpdateEntityVisible (void)
5126 {
5127         int i;
5128         int renderimask;
5129         int samples;
5130         entity_render_t *ent;
5131
5132         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5133                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5134                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5135                 :                                                          RENDER_EXTERIORMODEL;
5136         if (!r_drawviewmodel.integer)
5137                 renderimask |= RENDER_VIEWMODEL;
5138         if (!r_drawexteriormodel.integer)
5139                 renderimask |= RENDER_EXTERIORMODEL;
5140         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5141         {
5142                 // worldmodel can check visibility
5143                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5144                 for (i = 0;i < r_refdef.scene.numentities;i++)
5145                 {
5146                         ent = r_refdef.scene.entities[i];
5147                         if (!(ent->flags & renderimask))
5148                         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)))
5149                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5150                                 r_refdef.viewcache.entityvisible[i] = true;
5151                 }
5152         }
5153         else
5154         {
5155                 // no worldmodel or it can't check visibility
5156                 for (i = 0;i < r_refdef.scene.numentities;i++)
5157                 {
5158                         ent = r_refdef.scene.entities[i];
5159                         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));
5160                 }
5161         }
5162         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5163                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5164         {
5165                 for (i = 0;i < r_refdef.scene.numentities;i++)
5166                 {
5167                         if (!r_refdef.viewcache.entityvisible[i])
5168                                 continue;
5169                         ent = r_refdef.scene.entities[i];
5170                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5171                         {
5172                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5173                                 if (samples < 0)
5174                                         continue; // temp entities do pvs only
5175                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5176                                         ent->last_trace_visibility = realtime;
5177                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5178                                         r_refdef.viewcache.entityvisible[i] = 0;
5179                         }
5180                 }
5181         }
5182 }
5183
5184 /// only used if skyrendermasked, and normally returns false
5185 static int R_DrawBrushModelsSky (void)
5186 {
5187         int i, sky;
5188         entity_render_t *ent;
5189
5190         sky = false;
5191         for (i = 0;i < r_refdef.scene.numentities;i++)
5192         {
5193                 if (!r_refdef.viewcache.entityvisible[i])
5194                         continue;
5195                 ent = r_refdef.scene.entities[i];
5196                 if (!ent->model || !ent->model->DrawSky)
5197                         continue;
5198                 ent->model->DrawSky(ent);
5199                 sky = true;
5200         }
5201         return sky;
5202 }
5203
5204 static void R_DrawNoModel(entity_render_t *ent);
5205 static void R_DrawModels(void)
5206 {
5207         int i;
5208         entity_render_t *ent;
5209
5210         for (i = 0;i < r_refdef.scene.numentities;i++)
5211         {
5212                 if (!r_refdef.viewcache.entityvisible[i])
5213                         continue;
5214                 ent = r_refdef.scene.entities[i];
5215                 r_refdef.stats[r_stat_entities]++;
5216                 /*
5217                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5218                 {
5219                         vec3_t f, l, u, o;
5220                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5221                         Con_Printf("R_DrawModels\n");
5222                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5223                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5224                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5225                 }
5226                 */
5227                 if (ent->model && ent->model->Draw != NULL)
5228                         ent->model->Draw(ent);
5229                 else
5230                         R_DrawNoModel(ent);
5231         }
5232 }
5233
5234 static void R_DrawModelsDepth(void)
5235 {
5236         int i;
5237         entity_render_t *ent;
5238
5239         for (i = 0;i < r_refdef.scene.numentities;i++)
5240         {
5241                 if (!r_refdef.viewcache.entityvisible[i])
5242                         continue;
5243                 ent = r_refdef.scene.entities[i];
5244                 if (ent->model && ent->model->DrawDepth != NULL)
5245                         ent->model->DrawDepth(ent);
5246         }
5247 }
5248
5249 static void R_DrawModelsDebug(void)
5250 {
5251         int i;
5252         entity_render_t *ent;
5253
5254         for (i = 0;i < r_refdef.scene.numentities;i++)
5255         {
5256                 if (!r_refdef.viewcache.entityvisible[i])
5257                         continue;
5258                 ent = r_refdef.scene.entities[i];
5259                 if (ent->model && ent->model->DrawDebug != NULL)
5260                         ent->model->DrawDebug(ent);
5261         }
5262 }
5263
5264 static void R_DrawModelsAddWaterPlanes(void)
5265 {
5266         int i;
5267         entity_render_t *ent;
5268
5269         for (i = 0;i < r_refdef.scene.numentities;i++)
5270         {
5271                 if (!r_refdef.viewcache.entityvisible[i])
5272                         continue;
5273                 ent = r_refdef.scene.entities[i];
5274                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5275                         ent->model->DrawAddWaterPlanes(ent);
5276         }
5277 }
5278
5279 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5280
5281 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5282 {
5283         if (r_hdr_irisadaptation.integer)
5284         {
5285                 vec3_t p;
5286                 vec3_t ambient;
5287                 vec3_t diffuse;
5288                 vec3_t diffusenormal;
5289                 vec3_t forward;
5290                 vec_t brightness = 0.0f;
5291                 vec_t goal;
5292                 vec_t current;
5293                 vec_t d;
5294                 int c;
5295                 VectorCopy(r_refdef.view.forward, forward);
5296                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5297                 {
5298                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5299                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5300                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5301                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5302                         d = DotProduct(forward, diffusenormal);
5303                         brightness += VectorLength(ambient);
5304                         if (d > 0)
5305                                 brightness += d * VectorLength(diffuse);
5306                 }
5307                 brightness *= 1.0f / c;
5308                 brightness += 0.00001f; // make sure it's never zero
5309                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5310                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5311                 current = r_hdr_irisadaptation_value.value;
5312                 if (current < goal)
5313                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5314                 else if (current > goal)
5315                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5316                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5317                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5318         }
5319         else if (r_hdr_irisadaptation_value.value != 1.0f)
5320                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5321 }
5322
5323 static void R_View_SetFrustum(const int *scissor)
5324 {
5325         int i;
5326         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5327         vec3_t forward, left, up, origin, v;
5328
5329         if(scissor)
5330         {
5331                 // flipped x coordinates (because x points left here)
5332                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5333                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5334
5335                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5336                 switch(vid.renderpath)
5337                 {
5338                         case RENDERPATH_D3D9:
5339                         case RENDERPATH_D3D10:
5340                         case RENDERPATH_D3D11:
5341                                 // non-flipped y coordinates
5342                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5343                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5344                                 break;
5345                         case RENDERPATH_SOFT:
5346                         case RENDERPATH_GL11:
5347                         case RENDERPATH_GL13:
5348                         case RENDERPATH_GL20:
5349                         case RENDERPATH_GLES1:
5350                         case RENDERPATH_GLES2:
5351                                 // non-flipped y coordinates
5352                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5353                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5354                                 break;
5355                 }
5356         }
5357
5358         // we can't trust r_refdef.view.forward and friends in reflected scenes
5359         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5360
5361 #if 0
5362         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5363         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5364         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5365         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5366         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5367         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5368         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5369         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5370         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5371         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5372         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5373         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5374 #endif
5375
5376 #if 0
5377         zNear = r_refdef.nearclip;
5378         nudge = 1.0 - 1.0 / (1<<23);
5379         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5380         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5381         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5382         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5383         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5384         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5385         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5386         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5387 #endif
5388
5389
5390
5391 #if 0
5392         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5393         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5394         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5395         r_refdef.view.frustum[0].dist = m[15] - m[12];
5396
5397         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5398         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5399         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5400         r_refdef.view.frustum[1].dist = m[15] + m[12];
5401
5402         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5403         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5404         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5405         r_refdef.view.frustum[2].dist = m[15] - m[13];
5406
5407         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5408         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5409         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5410         r_refdef.view.frustum[3].dist = m[15] + m[13];
5411
5412         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5413         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5414         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5415         r_refdef.view.frustum[4].dist = m[15] - m[14];
5416
5417         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5418         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5419         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5420         r_refdef.view.frustum[5].dist = m[15] + m[14];
5421 #endif
5422
5423         if (r_refdef.view.useperspective)
5424         {
5425                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5426                 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]);
5427                 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]);
5428                 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]);
5429                 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]);
5430
5431                 // then the normals from the corners relative to origin
5432                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5433                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5434                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5435                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5436
5437                 // in a NORMAL view, forward cross left == up
5438                 // in a REFLECTED view, forward cross left == down
5439                 // so our cross products above need to be adjusted for a left handed coordinate system
5440                 CrossProduct(forward, left, v);
5441                 if(DotProduct(v, up) < 0)
5442                 {
5443                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5444                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5445                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5446                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5447                 }
5448
5449                 // Leaving those out was a mistake, those were in the old code, and they
5450                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5451                 // I couldn't reproduce it after adding those normalizations. --blub
5452                 VectorNormalize(r_refdef.view.frustum[0].normal);
5453                 VectorNormalize(r_refdef.view.frustum[1].normal);
5454                 VectorNormalize(r_refdef.view.frustum[2].normal);
5455                 VectorNormalize(r_refdef.view.frustum[3].normal);
5456
5457                 // make the corners absolute
5458                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5459                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5460                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5461                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5462
5463                 // one more normal
5464                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5465
5466                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5467                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5468                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5469                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5470                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5471         }
5472         else
5473         {
5474                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5475                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5476                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5477                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5478                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5479                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5480                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5481                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5482                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5483                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5484         }
5485         r_refdef.view.numfrustumplanes = 5;
5486
5487         if (r_refdef.view.useclipplane)
5488         {
5489                 r_refdef.view.numfrustumplanes = 6;
5490                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5491         }
5492
5493         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5494                 PlaneClassify(r_refdef.view.frustum + i);
5495
5496         // LordHavoc: note to all quake engine coders, Quake had a special case
5497         // for 90 degrees which assumed a square view (wrong), so I removed it,
5498         // Quake2 has it disabled as well.
5499
5500         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5501         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5502         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5503         //PlaneClassify(&frustum[0]);
5504
5505         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5506         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5507         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5508         //PlaneClassify(&frustum[1]);
5509
5510         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5511         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5512         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5513         //PlaneClassify(&frustum[2]);
5514
5515         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5516         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5517         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5518         //PlaneClassify(&frustum[3]);
5519
5520         // nearclip plane
5521         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5522         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5523         //PlaneClassify(&frustum[4]);
5524 }
5525
5526 static void R_View_UpdateWithScissor(const int *myscissor)
5527 {
5528         R_Main_ResizeViewCache();
5529         R_View_SetFrustum(myscissor);
5530         R_View_WorldVisibility(r_refdef.view.useclipplane);
5531         R_View_UpdateEntityVisible();
5532         R_View_UpdateEntityLighting();
5533 }
5534
5535 static void R_View_Update(void)
5536 {
5537         R_Main_ResizeViewCache();
5538         R_View_SetFrustum(NULL);
5539         R_View_WorldVisibility(r_refdef.view.useclipplane);
5540         R_View_UpdateEntityVisible();
5541         R_View_UpdateEntityLighting();
5542 }
5543
5544 float viewscalefpsadjusted = 1.0f;
5545
5546 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5547 {
5548         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5549         scale = bound(0.03125f, scale, 1.0f);
5550         *outwidth = (int)ceil(width * scale);
5551         *outheight = (int)ceil(height * scale);
5552 }
5553
5554 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5555 {
5556         const float *customclipplane = NULL;
5557         float plane[4];
5558         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5559         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5560         {
5561                 // LordHavoc: couldn't figure out how to make this approach the
5562                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5563                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5564                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5565                         dist = r_refdef.view.clipplane.dist;
5566                 plane[0] = r_refdef.view.clipplane.normal[0];
5567                 plane[1] = r_refdef.view.clipplane.normal[1];
5568                 plane[2] = r_refdef.view.clipplane.normal[2];
5569                 plane[3] = -dist;
5570                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5571         }
5572
5573         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5574         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5575
5576         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5577         if (!r_refdef.view.useperspective)
5578                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5579         else if (vid.stencil && r_useinfinitefarclip.integer)
5580                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5581         else
5582                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5583         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5584         R_SetViewport(&r_refdef.view.viewport);
5585         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5586         {
5587                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5588                 float screenplane[4];
5589                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5590                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5591                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5592                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5593                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5594         }
5595 }
5596
5597 void R_EntityMatrix(const matrix4x4_t *matrix)
5598 {
5599         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5600         {
5601                 gl_modelmatrixchanged = false;
5602                 gl_modelmatrix = *matrix;
5603                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5604                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5605                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5606                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5607                 CHECKGLERROR
5608                 switch(vid.renderpath)
5609                 {
5610                 case RENDERPATH_D3D9:
5611 #ifdef SUPPORTD3D
5612                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5613                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5614 #endif
5615                         break;
5616                 case RENDERPATH_D3D10:
5617                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5618                         break;
5619                 case RENDERPATH_D3D11:
5620                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5621                         break;
5622                 case RENDERPATH_GL11:
5623                 case RENDERPATH_GL13:
5624                 case RENDERPATH_GLES1:
5625                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5626                         break;
5627                 case RENDERPATH_SOFT:
5628                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5629                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5630                         break;
5631                 case RENDERPATH_GL20:
5632                 case RENDERPATH_GLES2:
5633                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5634                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5635                         break;
5636                 }
5637         }
5638 }
5639
5640 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5641 {
5642         r_viewport_t viewport;
5643
5644         CHECKGLERROR
5645
5646         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5647         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, x2, y2, -10, 100, NULL);
5648         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5649         R_SetViewport(&viewport);
5650         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5651         GL_Color(1, 1, 1, 1);
5652         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5653         GL_BlendFunc(GL_ONE, GL_ZERO);
5654         GL_ScissorTest(false);
5655         GL_DepthMask(false);
5656         GL_DepthRange(0, 1);
5657         GL_DepthTest(false);
5658         GL_DepthFunc(GL_LEQUAL);
5659         R_EntityMatrix(&identitymatrix);
5660         R_Mesh_ResetTextureState();
5661         GL_PolygonOffset(0, 0);
5662         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5663         switch(vid.renderpath)
5664         {
5665         case RENDERPATH_GL11:
5666         case RENDERPATH_GL13:
5667         case RENDERPATH_GL20:
5668         case RENDERPATH_GLES1:
5669         case RENDERPATH_GLES2:
5670                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5671                 break;
5672         case RENDERPATH_D3D9:
5673         case RENDERPATH_D3D10:
5674         case RENDERPATH_D3D11:
5675         case RENDERPATH_SOFT:
5676                 break;
5677         }
5678         GL_CullFace(GL_NONE);
5679
5680         CHECKGLERROR
5681 }
5682
5683 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5684 {
5685         DrawQ_Finish();
5686
5687         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5688 }
5689
5690 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5691 {
5692         DrawQ_Finish();
5693
5694         R_SetupView(true, fbo, depthtexture, colortexture);
5695         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5696         GL_Color(1, 1, 1, 1);
5697         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5698         GL_BlendFunc(GL_ONE, GL_ZERO);
5699         GL_ScissorTest(true);
5700         GL_DepthMask(true);
5701         GL_DepthRange(0, 1);
5702         GL_DepthTest(true);
5703         GL_DepthFunc(GL_LEQUAL);
5704         R_EntityMatrix(&identitymatrix);
5705         R_Mesh_ResetTextureState();
5706         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5707         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5708         switch(vid.renderpath)
5709         {
5710         case RENDERPATH_GL11:
5711         case RENDERPATH_GL13:
5712         case RENDERPATH_GL20:
5713         case RENDERPATH_GLES1:
5714         case RENDERPATH_GLES2:
5715                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5716                 break;
5717         case RENDERPATH_D3D9:
5718         case RENDERPATH_D3D10:
5719         case RENDERPATH_D3D11:
5720         case RENDERPATH_SOFT:
5721                 break;
5722         }
5723         GL_CullFace(r_refdef.view.cullface_back);
5724 }
5725
5726 /*
5727 ================
5728 R_RenderView_UpdateViewVectors
5729 ================
5730 */
5731 void R_RenderView_UpdateViewVectors(void)
5732 {
5733         // break apart the view matrix into vectors for various purposes
5734         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5735         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5736         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5737         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5738         // make an inverted copy of the view matrix for tracking sprites
5739         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5740 }
5741
5742 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5743 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5744
5745 static void R_Water_StartFrame(void)
5746 {
5747         int i;
5748         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5749         r_waterstate_waterplane_t *p;
5750         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5751
5752         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5753                 return;
5754
5755         switch(vid.renderpath)
5756         {
5757         case RENDERPATH_GL20:
5758         case RENDERPATH_D3D9:
5759         case RENDERPATH_D3D10:
5760         case RENDERPATH_D3D11:
5761         case RENDERPATH_SOFT:
5762         case RENDERPATH_GLES2:
5763                 break;
5764         case RENDERPATH_GL11:
5765         case RENDERPATH_GL13:
5766         case RENDERPATH_GLES1:
5767                 return;
5768         }
5769
5770         // set waterwidth and waterheight to the water resolution that will be
5771         // used (often less than the screen resolution for faster rendering)
5772         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5773
5774         // calculate desired texture sizes
5775         // can't use water if the card does not support the texture size
5776         if (!r_water.integer || r_showsurfaces.integer)
5777                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5778         else if (vid.support.arb_texture_non_power_of_two)
5779         {
5780                 texturewidth = waterwidth;
5781                 textureheight = waterheight;
5782                 camerawidth = waterwidth;
5783                 cameraheight = waterheight;
5784         }
5785         else
5786         {
5787                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5788                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5789                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5790                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5791         }
5792
5793         // allocate textures as needed
5794         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5795         {
5796                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5797                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5798                 {
5799                         if (p->texture_refraction)
5800                                 R_FreeTexture(p->texture_refraction);
5801                         p->texture_refraction = NULL;
5802                         if (p->fbo_refraction)
5803                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5804                         p->fbo_refraction = 0;
5805                         if (p->texture_reflection)
5806                                 R_FreeTexture(p->texture_reflection);
5807                         p->texture_reflection = NULL;
5808                         if (p->fbo_reflection)
5809                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5810                         p->fbo_reflection = 0;
5811                         if (p->texture_camera)
5812                                 R_FreeTexture(p->texture_camera);
5813                         p->texture_camera = NULL;
5814                         if (p->fbo_camera)
5815                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5816                         p->fbo_camera = 0;
5817                 }
5818                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5819                 r_fb.water.texturewidth = texturewidth;
5820                 r_fb.water.textureheight = textureheight;
5821                 r_fb.water.camerawidth = camerawidth;
5822                 r_fb.water.cameraheight = cameraheight;
5823         }
5824
5825         if (r_fb.water.texturewidth)
5826         {
5827                 int scaledwidth, scaledheight;
5828
5829                 r_fb.water.enabled = true;
5830
5831                 // water resolution is usually reduced
5832                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5833                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5834                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5835
5836                 // set up variables that will be used in shader setup
5837                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5838                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5839                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5840                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5841         }
5842
5843         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5844         r_fb.water.numwaterplanes = 0;
5845 }
5846
5847 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5848 {
5849         int planeindex, bestplaneindex, vertexindex;
5850         vec3_t mins, maxs, normal, center, v, n;
5851         vec_t planescore, bestplanescore;
5852         mplane_t plane;
5853         r_waterstate_waterplane_t *p;
5854         texture_t *t = R_GetCurrentTexture(surface->texture);
5855
5856         rsurface.texture = t;
5857         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5858         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5859         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5860                 return;
5861         // average the vertex normals, find the surface bounds (after deformvertexes)
5862         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5863         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5864         VectorCopy(n, normal);
5865         VectorCopy(v, mins);
5866         VectorCopy(v, maxs);
5867         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5868         {
5869                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5870                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5871                 VectorAdd(normal, n, normal);
5872                 mins[0] = min(mins[0], v[0]);
5873                 mins[1] = min(mins[1], v[1]);
5874                 mins[2] = min(mins[2], v[2]);
5875                 maxs[0] = max(maxs[0], v[0]);
5876                 maxs[1] = max(maxs[1], v[1]);
5877                 maxs[2] = max(maxs[2], v[2]);
5878         }
5879         VectorNormalize(normal);
5880         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5881
5882         VectorCopy(normal, plane.normal);
5883         VectorNormalize(plane.normal);
5884         plane.dist = DotProduct(center, plane.normal);
5885         PlaneClassify(&plane);
5886         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5887         {
5888                 // skip backfaces (except if nocullface is set)
5889 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5890 //                      return;
5891                 VectorNegate(plane.normal, plane.normal);
5892                 plane.dist *= -1;
5893                 PlaneClassify(&plane);
5894         }
5895
5896
5897         // find a matching plane if there is one
5898         bestplaneindex = -1;
5899         bestplanescore = 1048576.0f;
5900         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5901         {
5902                 if(p->camera_entity == t->camera_entity)
5903                 {
5904                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5905                         if (bestplaneindex < 0 || bestplanescore > planescore)
5906                         {
5907                                 bestplaneindex = planeindex;
5908                                 bestplanescore = planescore;
5909                         }
5910                 }
5911         }
5912         planeindex = bestplaneindex;
5913         p = r_fb.water.waterplanes + planeindex;
5914
5915         // if this surface does not fit any known plane rendered this frame, add one
5916         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5917         {
5918                 // store the new plane
5919                 planeindex = r_fb.water.numwaterplanes++;
5920                 p = r_fb.water.waterplanes + planeindex;
5921                 p->plane = plane;
5922                 // clear materialflags and pvs
5923                 p->materialflags = 0;
5924                 p->pvsvalid = false;
5925                 p->camera_entity = t->camera_entity;
5926                 VectorCopy(mins, p->mins);
5927                 VectorCopy(maxs, p->maxs);
5928         }
5929         else
5930         {
5931                 // merge mins/maxs when we're adding this surface to the plane
5932                 p->mins[0] = min(p->mins[0], mins[0]);
5933                 p->mins[1] = min(p->mins[1], mins[1]);
5934                 p->mins[2] = min(p->mins[2], mins[2]);
5935                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5936                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5937                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5938         }
5939         // merge this surface's materialflags into the waterplane
5940         p->materialflags |= t->currentmaterialflags;
5941         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5942         {
5943                 // merge this surface's PVS into the waterplane
5944                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5945                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5946                 {
5947                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5948                         p->pvsvalid = true;
5949                 }
5950         }
5951 }
5952
5953 extern cvar_t r_drawparticles;
5954 extern cvar_t r_drawdecals;
5955
5956 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5957 {
5958         int myscissor[4];
5959         r_refdef_view_t originalview;
5960         r_refdef_view_t myview;
5961         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5962         r_waterstate_waterplane_t *p;
5963         vec3_t visorigin;
5964         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5965         char vabuf[1024];
5966
5967         originalview = r_refdef.view;
5968
5969         // lowquality hack, temporarily shut down some cvars and restore afterwards
5970         qualityreduction = r_water_lowquality.integer;
5971         if (qualityreduction > 0)
5972         {
5973                 if (qualityreduction >= 1)
5974                 {
5975                         old_r_shadows = r_shadows.integer;
5976                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5977                         old_r_dlight = r_shadow_realtime_dlight.integer;
5978                         Cvar_SetValueQuick(&r_shadows, 0);
5979                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5980                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5981                 }
5982                 if (qualityreduction >= 2)
5983                 {
5984                         old_r_dynamic = r_dynamic.integer;
5985                         old_r_particles = r_drawparticles.integer;
5986                         old_r_decals = r_drawdecals.integer;
5987                         Cvar_SetValueQuick(&r_dynamic, 0);
5988                         Cvar_SetValueQuick(&r_drawparticles, 0);
5989                         Cvar_SetValueQuick(&r_drawdecals, 0);
5990                 }
5991         }
5992
5993         // make sure enough textures are allocated
5994         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5995         {
5996                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5997                 {
5998                         if (!p->texture_refraction)
5999                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6000                         if (!p->texture_refraction)
6001                                 goto error;
6002                         if (usewaterfbo)
6003                         {
6004                                 if (r_fb.water.depthtexture == NULL)
6005                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6006                                 if (p->fbo_refraction == 0)
6007                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6008                         }
6009                 }
6010                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6011                 {
6012                         if (!p->texture_camera)
6013                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6014                         if (!p->texture_camera)
6015                                 goto error;
6016                         if (usewaterfbo)
6017                         {
6018                                 if (r_fb.water.depthtexture == NULL)
6019                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6020                                 if (p->fbo_camera == 0)
6021                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6022                         }
6023                 }
6024
6025                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6026                 {
6027                         if (!p->texture_reflection)
6028                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6029                         if (!p->texture_reflection)
6030                                 goto error;
6031                         if (usewaterfbo)
6032                         {
6033                                 if (r_fb.water.depthtexture == NULL)
6034                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6035                                 if (p->fbo_reflection == 0)
6036                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6037                         }
6038                 }
6039         }
6040
6041         // render views
6042         r_refdef.view = originalview;
6043         r_refdef.view.showdebug = false;
6044         r_refdef.view.width = r_fb.water.waterwidth;
6045         r_refdef.view.height = r_fb.water.waterheight;
6046         r_refdef.view.useclipplane = true;
6047         myview = r_refdef.view;
6048         r_fb.water.renderingscene = true;
6049         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6050         {
6051                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6052                 {
6053                         r_refdef.view = myview;
6054                         if(r_water_scissormode.integer)
6055                         {
6056                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6057                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6058                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6059                         }
6060
6061                         // render reflected scene and copy into texture
6062                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6063                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6064                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6065                         r_refdef.view.clipplane = p->plane;
6066                         // reverse the cullface settings for this render
6067                         r_refdef.view.cullface_front = GL_FRONT;
6068                         r_refdef.view.cullface_back = GL_BACK;
6069                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6070                         {
6071                                 r_refdef.view.usecustompvs = true;
6072                                 if (p->pvsvalid)
6073                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6074                                 else
6075                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6076                         }
6077
6078                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6079                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6080                         R_ClearScreen(r_refdef.fogenabled);
6081                         if(r_water_scissormode.integer & 2)
6082                                 R_View_UpdateWithScissor(myscissor);
6083                         else
6084                                 R_View_Update();
6085                         R_AnimCache_CacheVisibleEntities();
6086                         if(r_water_scissormode.integer & 1)
6087                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6088                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6089
6090                         if (!p->fbo_reflection)
6091                                 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);
6092                         r_fb.water.hideplayer = false;
6093                 }
6094
6095                 // render the normal view scene and copy into texture
6096                 // (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)
6097                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6098                 {
6099                         r_refdef.view = myview;
6100                         if(r_water_scissormode.integer)
6101                         {
6102                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6103                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6104                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6105                         }
6106
6107                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6108
6109                         r_refdef.view.clipplane = p->plane;
6110                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6111                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6112
6113                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6114                         {
6115                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6116                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6117                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6118                                 R_RenderView_UpdateViewVectors();
6119                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6120                                 {
6121                                         r_refdef.view.usecustompvs = true;
6122                                         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);
6123                                 }
6124                         }
6125
6126                         PlaneClassify(&r_refdef.view.clipplane);
6127
6128                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6129                         R_ClearScreen(r_refdef.fogenabled);
6130                         if(r_water_scissormode.integer & 2)
6131                                 R_View_UpdateWithScissor(myscissor);
6132                         else
6133                                 R_View_Update();
6134                         R_AnimCache_CacheVisibleEntities();
6135                         if(r_water_scissormode.integer & 1)
6136                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6137                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6138
6139                         if (!p->fbo_refraction)
6140                                 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);
6141                         r_fb.water.hideplayer = false;
6142                 }
6143                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6144                 {
6145                         r_refdef.view = myview;
6146
6147                         r_refdef.view.clipplane = p->plane;
6148                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6149                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6150
6151                         r_refdef.view.width = r_fb.water.camerawidth;
6152                         r_refdef.view.height = r_fb.water.cameraheight;
6153                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6154                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6155                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6156                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6157
6158                         if(p->camera_entity)
6159                         {
6160                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6161                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6162                         }
6163
6164                         // note: all of the view is used for displaying... so
6165                         // there is no use in scissoring
6166
6167                         // reverse the cullface settings for this render
6168                         r_refdef.view.cullface_front = GL_FRONT;
6169                         r_refdef.view.cullface_back = GL_BACK;
6170                         // also reverse the view matrix
6171                         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
6172                         R_RenderView_UpdateViewVectors();
6173                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6174                         {
6175                                 r_refdef.view.usecustompvs = true;
6176                                 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);
6177                         }
6178                         
6179                         // camera needs no clipplane
6180                         r_refdef.view.useclipplane = false;
6181
6182                         PlaneClassify(&r_refdef.view.clipplane);
6183
6184                         r_fb.water.hideplayer = false;
6185
6186                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6187                         R_ClearScreen(r_refdef.fogenabled);
6188                         R_View_Update();
6189                         R_AnimCache_CacheVisibleEntities();
6190                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6191
6192                         if (!p->fbo_camera)
6193                                 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);
6194                         r_fb.water.hideplayer = false;
6195                 }
6196
6197         }
6198         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6199         r_fb.water.renderingscene = false;
6200         r_refdef.view = originalview;
6201         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6202         if (!r_fb.water.depthtexture)
6203                 R_ClearScreen(r_refdef.fogenabled);
6204         R_View_Update();
6205         R_AnimCache_CacheVisibleEntities();
6206         goto finish;
6207 error:
6208         r_refdef.view = originalview;
6209         r_fb.water.renderingscene = false;
6210         Cvar_SetValueQuick(&r_water, 0);
6211         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6212 finish:
6213         // lowquality hack, restore cvars
6214         if (qualityreduction > 0)
6215         {
6216                 if (qualityreduction >= 1)
6217                 {
6218                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6219                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6220                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6221                 }
6222                 if (qualityreduction >= 2)
6223                 {
6224                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6225                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6226                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6227                 }
6228         }
6229 }
6230
6231 static void R_Bloom_StartFrame(void)
6232 {
6233         int i;
6234         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6235         int viewwidth, viewheight;
6236         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6237         textype_t textype = TEXTYPE_COLORBUFFER;
6238
6239         switch (vid.renderpath)
6240         {
6241         case RENDERPATH_GL20:
6242                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6243                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6244                 {
6245                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6246                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6247                 }
6248                 break;
6249         case RENDERPATH_GL11:
6250         case RENDERPATH_GL13:
6251         case RENDERPATH_GLES1:
6252         case RENDERPATH_GLES2:
6253         case RENDERPATH_D3D9:
6254         case RENDERPATH_D3D10:
6255         case RENDERPATH_D3D11:
6256                 r_fb.usedepthtextures = false;
6257                 break;
6258         case RENDERPATH_SOFT:
6259                 r_fb.usedepthtextures = true;
6260                 break;
6261         }
6262
6263         if (r_viewscale_fpsscaling.integer)
6264         {
6265                 double actualframetime;
6266                 double targetframetime;
6267                 double adjust;
6268                 actualframetime = r_refdef.lastdrawscreentime;
6269                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6270                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6271                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6272                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6273                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6274                 viewscalefpsadjusted += adjust;
6275                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6276         }
6277         else
6278                 viewscalefpsadjusted = 1.0f;
6279
6280         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6281
6282         switch(vid.renderpath)
6283         {
6284         case RENDERPATH_GL20:
6285         case RENDERPATH_D3D9:
6286         case RENDERPATH_D3D10:
6287         case RENDERPATH_D3D11:
6288         case RENDERPATH_SOFT:
6289         case RENDERPATH_GLES2:
6290                 break;
6291         case RENDERPATH_GL11:
6292         case RENDERPATH_GL13:
6293         case RENDERPATH_GLES1:
6294                 return;
6295         }
6296
6297         // set bloomwidth and bloomheight to the bloom resolution that will be
6298         // used (often less than the screen resolution for faster rendering)
6299         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6300         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6301         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6302         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6303         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6304
6305         // calculate desired texture sizes
6306         if (vid.support.arb_texture_non_power_of_two)
6307         {
6308                 screentexturewidth = vid.width;
6309                 screentextureheight = vid.height;
6310                 bloomtexturewidth = r_fb.bloomwidth;
6311                 bloomtextureheight = r_fb.bloomheight;
6312         }
6313         else
6314         {
6315                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6316                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6317                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6318                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6319         }
6320
6321         if ((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))
6322         {
6323                 Cvar_SetValueQuick(&r_bloom, 0);
6324                 Cvar_SetValueQuick(&r_motionblur, 0);
6325                 Cvar_SetValueQuick(&r_damageblur, 0);
6326         }
6327
6328         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6329          && !r_bloom.integer
6330          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6331          && !useviewfbo
6332          && r_viewscale.value == 1.0f
6333          && !r_viewscale_fpsscaling.integer)
6334                 screentexturewidth = screentextureheight = 0;
6335         if (!r_bloom.integer)
6336                 bloomtexturewidth = bloomtextureheight = 0;
6337
6338         // allocate textures as needed
6339         if (r_fb.screentexturewidth != screentexturewidth
6340          || r_fb.screentextureheight != screentextureheight
6341          || r_fb.bloomtexturewidth != bloomtexturewidth
6342          || r_fb.bloomtextureheight != bloomtextureheight
6343          || r_fb.textype != textype
6344          || useviewfbo != (r_fb.fbo != 0))
6345         {
6346                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6347                 {
6348                         if (r_fb.bloomtexture[i])
6349                                 R_FreeTexture(r_fb.bloomtexture[i]);
6350                         r_fb.bloomtexture[i] = NULL;
6351
6352                         if (r_fb.bloomfbo[i])
6353                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6354                         r_fb.bloomfbo[i] = 0;
6355                 }
6356
6357                 if (r_fb.fbo)
6358                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6359                 r_fb.fbo = 0;
6360
6361                 if (r_fb.colortexture)
6362                         R_FreeTexture(r_fb.colortexture);
6363                 r_fb.colortexture = NULL;
6364
6365                 if (r_fb.depthtexture)
6366                         R_FreeTexture(r_fb.depthtexture);
6367                 r_fb.depthtexture = NULL;
6368
6369                 if (r_fb.ghosttexture)
6370                         R_FreeTexture(r_fb.ghosttexture);
6371                 r_fb.ghosttexture = NULL;
6372
6373                 r_fb.screentexturewidth = screentexturewidth;
6374                 r_fb.screentextureheight = screentextureheight;
6375                 r_fb.bloomtexturewidth = bloomtexturewidth;
6376                 r_fb.bloomtextureheight = bloomtextureheight;
6377                 r_fb.textype = textype;
6378
6379                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6380                 {
6381                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6382                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6383                         r_fb.ghosttexture_valid = false;
6384                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6385                         if (useviewfbo)
6386                         {
6387                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6388                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6389                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6390                         }
6391                 }
6392
6393                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6394                 {
6395                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6396                         {
6397                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6398                                 if (useviewfbo)
6399                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6400                         }
6401                 }
6402         }
6403
6404         // bloom texture is a different resolution
6405         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6406         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6407         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6408         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6409         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6410
6411         // set up a texcoord array for the full resolution screen image
6412         // (we have to keep this around to copy back during final render)
6413         r_fb.screentexcoord2f[0] = 0;
6414         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6415         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6416         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6417         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6418         r_fb.screentexcoord2f[5] = 0;
6419         r_fb.screentexcoord2f[6] = 0;
6420         r_fb.screentexcoord2f[7] = 0;
6421
6422         if(r_fb.fbo) 
6423         {
6424                 for (i = 1;i < 8;i += 2)
6425                 {
6426                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6427                 }
6428         }
6429
6430         // set up a texcoord array for the reduced resolution bloom image
6431         // (which will be additive blended over the screen image)
6432         r_fb.bloomtexcoord2f[0] = 0;
6433         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6434         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6435         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6436         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6437         r_fb.bloomtexcoord2f[5] = 0;
6438         r_fb.bloomtexcoord2f[6] = 0;
6439         r_fb.bloomtexcoord2f[7] = 0;
6440
6441         switch(vid.renderpath)
6442         {
6443         case RENDERPATH_GL11:
6444         case RENDERPATH_GL13:
6445         case RENDERPATH_GL20:
6446         case RENDERPATH_SOFT:
6447         case RENDERPATH_GLES1:
6448         case RENDERPATH_GLES2:
6449                 break;
6450         case RENDERPATH_D3D9:
6451         case RENDERPATH_D3D10:
6452         case RENDERPATH_D3D11:
6453                 for (i = 0;i < 4;i++)
6454                 {
6455                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6456                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6457                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6458                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6459                 }
6460                 break;
6461         }
6462
6463         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6464
6465         if (r_fb.fbo)
6466                 r_refdef.view.clear = true;
6467 }
6468
6469 static void R_Bloom_MakeTexture(void)
6470 {
6471         int x, range, dir;
6472         float xoffset, yoffset, r, brighten;
6473         rtexture_t *intex;
6474         float colorscale = r_bloom_colorscale.value;
6475
6476         r_refdef.stats[r_stat_bloom]++;
6477     
6478 #if 0
6479     // this copy is unnecessary since it happens in R_BlendView already
6480         if (!r_fb.fbo)
6481         {
6482                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6483                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6484         }
6485 #endif
6486
6487         // scale down screen texture to the bloom texture size
6488         CHECKGLERROR
6489         r_fb.bloomindex = 0;
6490         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6491         R_SetViewport(&r_fb.bloomviewport);
6492         GL_DepthTest(false);
6493         GL_BlendFunc(GL_ONE, GL_ZERO);
6494         GL_Color(colorscale, colorscale, colorscale, 1);
6495         // 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...
6496         switch(vid.renderpath)
6497         {
6498         case RENDERPATH_GL11:
6499         case RENDERPATH_GL13:
6500         case RENDERPATH_GL20:
6501         case RENDERPATH_GLES1:
6502         case RENDERPATH_GLES2:
6503         case RENDERPATH_SOFT:
6504                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6505                 break;
6506         case RENDERPATH_D3D9:
6507         case RENDERPATH_D3D10:
6508         case RENDERPATH_D3D11:
6509                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6510                 break;
6511         }
6512         // TODO: do boxfilter scale-down in shader?
6513         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6514         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6515         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6516
6517         // we now have a properly scaled bloom image
6518         if (!r_fb.bloomfbo[r_fb.bloomindex])
6519         {
6520                 // copy it into the bloom texture
6521                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6522                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6523         }
6524
6525         // multiply bloom image by itself as many times as desired
6526         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6527         {
6528                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6529                 r_fb.bloomindex ^= 1;
6530                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6531                 x *= 2;
6532                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6533                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6534                 {
6535                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6536                         GL_Color(r,r,r,1); // apply fix factor
6537                 }
6538                 else
6539                 {
6540                         if(x <= 2)
6541                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6542                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6543                         GL_Color(1,1,1,1); // no fix factor supported here
6544                 }
6545                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6546                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6547                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6548                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6549
6550                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6551                 {
6552                         // copy the darkened image to a texture
6553                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6554                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6555                 }
6556         }
6557
6558         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6559         brighten = r_bloom_brighten.value;
6560         brighten = sqrt(brighten);
6561         if(range >= 1)
6562                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6563
6564         for (dir = 0;dir < 2;dir++)
6565         {
6566                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6567                 r_fb.bloomindex ^= 1;
6568                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6569                 // blend on at multiple vertical offsets to achieve a vertical blur
6570                 // TODO: do offset blends using GLSL
6571                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6572                 GL_BlendFunc(GL_ONE, GL_ZERO);
6573                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6574                 for (x = -range;x <= range;x++)
6575                 {
6576                         if (!dir){xoffset = 0;yoffset = x;}
6577                         else {xoffset = x;yoffset = 0;}
6578                         xoffset /= (float)r_fb.bloomtexturewidth;
6579                         yoffset /= (float)r_fb.bloomtextureheight;
6580                         // compute a texcoord array with the specified x and y offset
6581                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6582                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6583                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6584                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6585                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6586                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6587                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6588                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6589                         // this r value looks like a 'dot' particle, fading sharply to
6590                         // black at the edges
6591                         // (probably not realistic but looks good enough)
6592                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6593                         //r = brighten/(range*2+1);
6594                         r = brighten / (range * 2 + 1);
6595                         if(range >= 1)
6596                                 r *= (1 - x*x/(float)(range*range));
6597                         GL_Color(r, r, r, 1);
6598                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6599                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6600                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6601                         GL_BlendFunc(GL_ONE, GL_ONE);
6602                 }
6603
6604                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6605                 {
6606                         // copy the vertically or horizontally blurred bloom view to a texture
6607                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6608                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6609                 }
6610         }
6611 }
6612
6613 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6614 {
6615         unsigned int permutation;
6616         float uservecs[4][4];
6617
6618         R_EntityMatrix(&identitymatrix);
6619
6620         switch (vid.renderpath)
6621         {
6622         case RENDERPATH_GL20:
6623         case RENDERPATH_D3D9:
6624         case RENDERPATH_D3D10:
6625         case RENDERPATH_D3D11:
6626         case RENDERPATH_SOFT:
6627         case RENDERPATH_GLES2:
6628                 permutation =
6629                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6630                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6631                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6632                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6633                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6634
6635                 if (r_fb.colortexture)
6636                 {
6637                         if (!r_fb.fbo)
6638                         {
6639                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6640                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6641                         }
6642
6643                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6644                         {
6645                                 // declare variables
6646                                 float blur_factor, blur_mouseaccel, blur_velocity;
6647                                 static float blur_average; 
6648                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6649
6650                                 // set a goal for the factoring
6651                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6652                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6653                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6654                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6655                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6656                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6657
6658                                 // from the goal, pick an averaged value between goal and last value
6659                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6660                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6661
6662                                 // enforce minimum amount of blur 
6663                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6664
6665                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6666
6667                                 // calculate values into a standard alpha
6668                                 cl.motionbluralpha = 1 - exp(-
6669                                                 (
6670                                                  (r_motionblur.value * blur_factor / 80)
6671                                                  +
6672                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6673                                                 )
6674                                                 /
6675                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6676                                           );
6677
6678                                 // randomization for the blur value to combat persistent ghosting
6679                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6680                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6681
6682                                 // apply the blur
6683                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6684                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6685                                 {
6686                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6687                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6688                                         switch(vid.renderpath)
6689                                         {
6690                                         case RENDERPATH_GL11:
6691                                         case RENDERPATH_GL13:
6692                                         case RENDERPATH_GL20:
6693                                         case RENDERPATH_GLES1:
6694                                         case RENDERPATH_GLES2:
6695                                         case RENDERPATH_SOFT:
6696                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6697                                                 break;
6698                                         case RENDERPATH_D3D9:
6699                                         case RENDERPATH_D3D10:
6700                                         case RENDERPATH_D3D11:
6701                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6702                                                 break;
6703                                         }
6704                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6705                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6706                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6707                                 }
6708
6709                                 // updates old view angles for next pass
6710                                 VectorCopy(cl.viewangles, blur_oldangles);
6711
6712                                 // copy view into the ghost texture
6713                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6714                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6715                                 r_fb.ghosttexture_valid = true;
6716                         }
6717                 }
6718                 else
6719                 {
6720                         // no r_fb.colortexture means we're rendering to the real fb
6721                         // we may still have to do view tint...
6722                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6723                         {
6724                                 // apply a color tint to the whole view
6725                                 R_ResetViewRendering2D(0, NULL, NULL);
6726                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6727                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6728                                 R_SetupShader_Generic_NoTexture(false, true);
6729                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6730                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6731                         }
6732                         break; // no screen processing, no bloom, skip it
6733                 }
6734
6735                 if (r_fb.bloomtexture[0])
6736                 {
6737                         // make the bloom texture
6738                         R_Bloom_MakeTexture();
6739                 }
6740
6741 #if _MSC_VER >= 1400
6742 #define sscanf sscanf_s
6743 #endif
6744                 memset(uservecs, 0, sizeof(uservecs));
6745                 if (r_glsl_postprocess_uservec1_enable.integer)
6746                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6747                 if (r_glsl_postprocess_uservec2_enable.integer)
6748                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6749                 if (r_glsl_postprocess_uservec3_enable.integer)
6750                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6751                 if (r_glsl_postprocess_uservec4_enable.integer)
6752                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6753
6754                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6755                 GL_Color(1, 1, 1, 1);
6756                 GL_BlendFunc(GL_ONE, GL_ZERO);
6757
6758                 switch(vid.renderpath)
6759                 {
6760                 case RENDERPATH_GL20:
6761                 case RENDERPATH_GLES2:
6762                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6763                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6764                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6765                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6766                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6767                         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]);
6768                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6769                         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]);
6770                         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]);
6771                         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]);
6772                         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]);
6773                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6774                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6775                         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);
6776                         break;
6777                 case RENDERPATH_D3D9:
6778 #ifdef SUPPORTD3D
6779                         // 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...
6780                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6781                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6782                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6783                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6784                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6785                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6786                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6787                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6788                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6789                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6790                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6791                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6792                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6793                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6794 #endif
6795                         break;
6796                 case RENDERPATH_D3D10:
6797                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6798                         break;
6799                 case RENDERPATH_D3D11:
6800                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6801                         break;
6802                 case RENDERPATH_SOFT:
6803                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6804                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6805                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6806                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6807                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6808                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6809                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6810                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6811                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6812                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6813                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6814                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6815                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6816                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6817                         break;
6818                 default:
6819                         break;
6820                 }
6821                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6822                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6823                 break;
6824         case RENDERPATH_GL11:
6825         case RENDERPATH_GL13:
6826         case RENDERPATH_GLES1:
6827                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6828                 {
6829                         // apply a color tint to the whole view
6830                         R_ResetViewRendering2D(0, NULL, NULL);
6831                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6832                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6833                         R_SetupShader_Generic_NoTexture(false, true);
6834                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6835                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6836                 }
6837                 break;
6838         }
6839 }
6840
6841 matrix4x4_t r_waterscrollmatrix;
6842
6843 void R_UpdateFog(void)
6844 {
6845         // Nehahra fog
6846         if (gamemode == GAME_NEHAHRA)
6847         {
6848                 if (gl_fogenable.integer)
6849                 {
6850                         r_refdef.oldgl_fogenable = true;
6851                         r_refdef.fog_density = gl_fogdensity.value;
6852                         r_refdef.fog_red = gl_fogred.value;
6853                         r_refdef.fog_green = gl_foggreen.value;
6854                         r_refdef.fog_blue = gl_fogblue.value;
6855                         r_refdef.fog_alpha = 1;
6856                         r_refdef.fog_start = 0;
6857                         r_refdef.fog_end = gl_skyclip.value;
6858                         r_refdef.fog_height = 1<<30;
6859                         r_refdef.fog_fadedepth = 128;
6860                 }
6861                 else if (r_refdef.oldgl_fogenable)
6862                 {
6863                         r_refdef.oldgl_fogenable = false;
6864                         r_refdef.fog_density = 0;
6865                         r_refdef.fog_red = 0;
6866                         r_refdef.fog_green = 0;
6867                         r_refdef.fog_blue = 0;
6868                         r_refdef.fog_alpha = 0;
6869                         r_refdef.fog_start = 0;
6870                         r_refdef.fog_end = 0;
6871                         r_refdef.fog_height = 1<<30;
6872                         r_refdef.fog_fadedepth = 128;
6873                 }
6874         }
6875
6876         // fog parms
6877         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6878         r_refdef.fog_start = max(0, r_refdef.fog_start);
6879         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6880
6881         if (r_refdef.fog_density && r_drawfog.integer)
6882         {
6883                 r_refdef.fogenabled = true;
6884                 // this is the point where the fog reaches 0.9986 alpha, which we
6885                 // consider a good enough cutoff point for the texture
6886                 // (0.9986 * 256 == 255.6)
6887                 if (r_fog_exp2.integer)
6888                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6889                 else
6890                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6891                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6892                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6893                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6894                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6895                         R_BuildFogHeightTexture();
6896                 // fog color was already set
6897                 // update the fog texture
6898                 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)
6899                         R_BuildFogTexture();
6900                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6901                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6902         }
6903         else
6904                 r_refdef.fogenabled = false;
6905
6906         // fog color
6907         if (r_refdef.fog_density)
6908         {
6909                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6910                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6911                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6912
6913                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6914                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6915                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6916                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6917
6918                 {
6919                         vec3_t fogvec;
6920                         VectorCopy(r_refdef.fogcolor, fogvec);
6921                         //   color.rgb *= ContrastBoost * SceneBrightness;
6922                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6923                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6924                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6925                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6926                 }
6927         }
6928 }
6929
6930 void R_UpdateVariables(void)
6931 {
6932         R_Textures_Frame();
6933
6934         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6935
6936         r_refdef.farclip = r_farclip_base.value;
6937         if (r_refdef.scene.worldmodel)
6938                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6939         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6940
6941         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6942                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6943         r_refdef.polygonfactor = 0;
6944         r_refdef.polygonoffset = 0;
6945         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6946         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6947
6948         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6949         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6950         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6951         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6952         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6953         if (FAKELIGHT_ENABLED)
6954         {
6955                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6956         }
6957         else if (r_refdef.scene.worldmodel)
6958         {
6959                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6960         }
6961         if (r_showsurfaces.integer)
6962         {
6963                 r_refdef.scene.rtworld = false;
6964                 r_refdef.scene.rtworldshadows = false;
6965                 r_refdef.scene.rtdlight = false;
6966                 r_refdef.scene.rtdlightshadows = false;
6967                 r_refdef.lightmapintensity = 0;
6968         }
6969
6970         r_gpuskeletal = false;
6971         switch(vid.renderpath)
6972         {
6973         case RENDERPATH_GL20:
6974                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6975         case RENDERPATH_D3D9:
6976         case RENDERPATH_D3D10:
6977         case RENDERPATH_D3D11:
6978         case RENDERPATH_SOFT:
6979         case RENDERPATH_GLES2:
6980                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6981                 {
6982                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6983                         {
6984                                 // build GLSL gamma texture
6985 #define RAMPWIDTH 256
6986                                 unsigned short ramp[RAMPWIDTH * 3];
6987                                 unsigned char rampbgr[RAMPWIDTH][4];
6988                                 int i;
6989
6990                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6991
6992                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6993                                 for(i = 0; i < RAMPWIDTH; ++i)
6994                                 {
6995                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6996                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6997                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6998                                         rampbgr[i][3] = 0;
6999                                 }
7000                                 if (r_texture_gammaramps)
7001                                 {
7002                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7003                                 }
7004                                 else
7005                                 {
7006                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7007                                 }
7008                         }
7009                 }
7010                 else
7011                 {
7012                         // remove GLSL gamma texture
7013                 }
7014                 break;
7015         case RENDERPATH_GL11:
7016         case RENDERPATH_GL13:
7017         case RENDERPATH_GLES1:
7018                 break;
7019         }
7020 }
7021
7022 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7023 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7024 /*
7025 ================
7026 R_SelectScene
7027 ================
7028 */
7029 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7030         if( scenetype != r_currentscenetype ) {
7031                 // store the old scenetype
7032                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7033                 r_currentscenetype = scenetype;
7034                 // move in the new scene
7035                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7036         }
7037 }
7038
7039 /*
7040 ================
7041 R_GetScenePointer
7042 ================
7043 */
7044 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7045 {
7046         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7047         if( scenetype == r_currentscenetype ) {
7048                 return &r_refdef.scene;
7049         } else {
7050                 return &r_scenes_store[ scenetype ];
7051         }
7052 }
7053
7054 static int R_SortEntities_Compare(const void *ap, const void *bp)
7055 {
7056         const entity_render_t *a = *(const entity_render_t **)ap;
7057         const entity_render_t *b = *(const entity_render_t **)bp;
7058
7059         // 1. compare model
7060         if(a->model < b->model)
7061                 return -1;
7062         if(a->model > b->model)
7063                 return +1;
7064
7065         // 2. compare skin
7066         // TODO possibly calculate the REAL skinnum here first using
7067         // skinscenes?
7068         if(a->skinnum < b->skinnum)
7069                 return -1;
7070         if(a->skinnum > b->skinnum)
7071                 return +1;
7072
7073         // everything we compared is equal
7074         return 0;
7075 }
7076 static void R_SortEntities(void)
7077 {
7078         // below or equal 2 ents, sorting never gains anything
7079         if(r_refdef.scene.numentities <= 2)
7080                 return;
7081         // sort
7082         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7083 }
7084
7085 /*
7086 ================
7087 R_RenderView
7088 ================
7089 */
7090 int dpsoftrast_test;
7091 extern cvar_t r_shadow_bouncegrid;
7092 void R_RenderView(void)
7093 {
7094         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7095         int fbo;
7096         rtexture_t *depthtexture;
7097         rtexture_t *colortexture;
7098
7099         dpsoftrast_test = r_test.integer;
7100
7101         if (r_timereport_active)
7102                 R_TimeReport("start");
7103         r_textureframe++; // used only by R_GetCurrentTexture
7104         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7105
7106         if(R_CompileShader_CheckStaticParms())
7107                 R_GLSL_Restart_f();
7108
7109         if (!r_drawentities.integer)
7110                 r_refdef.scene.numentities = 0;
7111         else if (r_sortentities.integer)
7112                 R_SortEntities();
7113
7114         R_AnimCache_ClearCache();
7115         R_FrameData_NewFrame();
7116         R_BufferData_NewFrame();
7117
7118         /* adjust for stereo display */
7119         if(R_Stereo_Active())
7120         {
7121                 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);
7122                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7123         }
7124
7125         if (r_refdef.view.isoverlay)
7126         {
7127                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7128                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7129                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7130                 R_TimeReport("depthclear");
7131
7132                 r_refdef.view.showdebug = false;
7133
7134                 r_fb.water.enabled = false;
7135                 r_fb.water.numwaterplanes = 0;
7136
7137                 R_RenderScene(0, NULL, NULL);
7138
7139                 r_refdef.view.matrix = originalmatrix;
7140
7141                 CHECKGLERROR
7142                 return;
7143         }
7144
7145         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7146         {
7147                 r_refdef.view.matrix = originalmatrix;
7148                 return;
7149         }
7150
7151         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7152
7153         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7154                 // in sRGB fallback, behave similar to true sRGB: convert this
7155                 // value from linear to sRGB
7156                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7157
7158         R_RenderView_UpdateViewVectors();
7159
7160         R_Shadow_UpdateWorldLightSelection();
7161
7162         R_Bloom_StartFrame();
7163
7164         // apply bloom brightness offset
7165         if(r_fb.bloomtexture[0])
7166                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7167
7168         R_Water_StartFrame();
7169
7170         // now we probably have an fbo to render into
7171         fbo = r_fb.fbo;
7172         depthtexture = r_fb.depthtexture;
7173         colortexture = r_fb.colortexture;
7174
7175         CHECKGLERROR
7176         if (r_timereport_active)
7177                 R_TimeReport("viewsetup");
7178
7179         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7180
7181         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7182         {
7183                 R_ClearScreen(r_refdef.fogenabled);
7184                 if (r_timereport_active)
7185                         R_TimeReport("viewclear");
7186         }
7187         r_refdef.view.clear = true;
7188
7189         r_refdef.view.showdebug = true;
7190
7191         R_View_Update();
7192         if (r_timereport_active)
7193                 R_TimeReport("visibility");
7194
7195         R_AnimCache_CacheVisibleEntities();
7196         if (r_timereport_active)
7197                 R_TimeReport("animcache");
7198
7199         R_Shadow_UpdateBounceGridTexture();
7200         if (r_timereport_active && r_shadow_bouncegrid.integer)
7201                 R_TimeReport("bouncegrid");
7202
7203         r_fb.water.numwaterplanes = 0;
7204         if (r_fb.water.enabled)
7205                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7206
7207         R_RenderScene(fbo, depthtexture, colortexture);
7208         r_fb.water.numwaterplanes = 0;
7209
7210         R_BlendView(fbo, depthtexture, colortexture);
7211         if (r_timereport_active)
7212                 R_TimeReport("blendview");
7213
7214         GL_Scissor(0, 0, vid.width, vid.height);
7215         GL_ScissorTest(false);
7216
7217         r_refdef.view.matrix = originalmatrix;
7218
7219         CHECKGLERROR
7220 }
7221
7222 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7223 {
7224         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7225         {
7226                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7227                 if (r_timereport_active)
7228                         R_TimeReport("waterworld");
7229         }
7230
7231         // don't let sound skip if going slow
7232         if (r_refdef.scene.extraupdate)
7233                 S_ExtraUpdate ();
7234
7235         R_DrawModelsAddWaterPlanes();
7236         if (r_timereport_active)
7237                 R_TimeReport("watermodels");
7238
7239         if (r_fb.water.numwaterplanes)
7240         {
7241                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7242                 if (r_timereport_active)
7243                         R_TimeReport("waterscenes");
7244         }
7245 }
7246
7247 extern cvar_t cl_locs_show;
7248 static void R_DrawLocs(void);
7249 static void R_DrawEntityBBoxes(void);
7250 static void R_DrawModelDecals(void);
7251 extern cvar_t cl_decals_newsystem;
7252 extern qboolean r_shadow_usingdeferredprepass;
7253 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7254 {
7255         qboolean shadowmapping = false;
7256
7257         if (r_timereport_active)
7258                 R_TimeReport("beginscene");
7259
7260         r_refdef.stats[r_stat_renders]++;
7261
7262         R_UpdateFog();
7263
7264         // don't let sound skip if going slow
7265         if (r_refdef.scene.extraupdate)
7266                 S_ExtraUpdate ();
7267
7268         R_MeshQueue_BeginScene();
7269
7270         R_SkyStartFrame();
7271
7272         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);
7273
7274         if (r_timereport_active)
7275                 R_TimeReport("skystartframe");
7276
7277         if (cl.csqc_vidvars.drawworld)
7278         {
7279                 // don't let sound skip if going slow
7280                 if (r_refdef.scene.extraupdate)
7281                         S_ExtraUpdate ();
7282
7283                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7284                 {
7285                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7286                         if (r_timereport_active)
7287                                 R_TimeReport("worldsky");
7288                 }
7289
7290                 if (R_DrawBrushModelsSky() && r_timereport_active)
7291                         R_TimeReport("bmodelsky");
7292
7293                 if (skyrendermasked && skyrenderlater)
7294                 {
7295                         // we have to force off the water clipping plane while rendering sky
7296                         R_SetupView(false, fbo, depthtexture, colortexture);
7297                         R_Sky();
7298                         R_SetupView(true, fbo, depthtexture, colortexture);
7299                         if (r_timereport_active)
7300                                 R_TimeReport("sky");
7301                 }
7302         }
7303
7304         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7305         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7306                 R_Shadow_PrepareModelShadows();
7307         if (r_timereport_active)
7308                 R_TimeReport("preparelights");
7309
7310         if (R_Shadow_ShadowMappingEnabled())
7311                 shadowmapping = true;
7312
7313         if (r_shadow_usingdeferredprepass)
7314                 R_Shadow_DrawPrepass();
7315
7316         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7317         {
7318                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7319                 if (r_timereport_active)
7320                         R_TimeReport("worlddepth");
7321         }
7322         if (r_depthfirst.integer >= 2)
7323         {
7324                 R_DrawModelsDepth();
7325                 if (r_timereport_active)
7326                         R_TimeReport("modeldepth");
7327         }
7328
7329         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7330         {
7331                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7332                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7333                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7334                 // don't let sound skip if going slow
7335                 if (r_refdef.scene.extraupdate)
7336                         S_ExtraUpdate ();
7337         }
7338
7339         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7340         {
7341                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7342                 if (r_timereport_active)
7343                         R_TimeReport("world");
7344         }
7345
7346         // don't let sound skip if going slow
7347         if (r_refdef.scene.extraupdate)
7348                 S_ExtraUpdate ();
7349
7350         R_DrawModels();
7351         if (r_timereport_active)
7352                 R_TimeReport("models");
7353
7354         // don't let sound skip if going slow
7355         if (r_refdef.scene.extraupdate)
7356                 S_ExtraUpdate ();
7357
7358         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7359         {
7360                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7361                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7362                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7363                 // don't let sound skip if going slow
7364                 if (r_refdef.scene.extraupdate)
7365                         S_ExtraUpdate ();
7366         }
7367
7368         if (!r_shadow_usingdeferredprepass)
7369         {
7370                 R_Shadow_DrawLights();
7371                 if (r_timereport_active)
7372                         R_TimeReport("rtlights");
7373         }
7374
7375         // don't let sound skip if going slow
7376         if (r_refdef.scene.extraupdate)
7377                 S_ExtraUpdate ();
7378
7379         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7380         {
7381                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7382                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7383                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7384                 // don't let sound skip if going slow
7385                 if (r_refdef.scene.extraupdate)
7386                         S_ExtraUpdate ();
7387         }
7388
7389         if (cl.csqc_vidvars.drawworld)
7390         {
7391                 if (cl_decals_newsystem.integer)
7392                 {
7393                         R_DrawModelDecals();
7394                         if (r_timereport_active)
7395                                 R_TimeReport("modeldecals");
7396                 }
7397                 else
7398                 {
7399                         R_DrawDecals();
7400                         if (r_timereport_active)
7401                                 R_TimeReport("decals");
7402                 }
7403
7404                 R_DrawParticles();
7405                 if (r_timereport_active)
7406                         R_TimeReport("particles");
7407
7408                 R_DrawExplosions();
7409                 if (r_timereport_active)
7410                         R_TimeReport("explosions");
7411
7412                 R_DrawLightningBeams();
7413                 if (r_timereport_active)
7414                         R_TimeReport("lightning");
7415         }
7416
7417         if (cl.csqc_loaded)
7418                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7419
7420         if (r_refdef.view.showdebug)
7421         {
7422                 if (cl_locs_show.integer)
7423                 {
7424                         R_DrawLocs();
7425                         if (r_timereport_active)
7426                                 R_TimeReport("showlocs");
7427                 }
7428
7429                 if (r_drawportals.integer)
7430                 {
7431                         R_DrawPortals();
7432                         if (r_timereport_active)
7433                                 R_TimeReport("portals");
7434                 }
7435
7436                 if (r_showbboxes.value > 0)
7437                 {
7438                         R_DrawEntityBBoxes();
7439                         if (r_timereport_active)
7440                                 R_TimeReport("bboxes");
7441                 }
7442         }
7443
7444         if (r_transparent.integer)
7445         {
7446                 R_MeshQueue_RenderTransparent();
7447                 if (r_timereport_active)
7448                         R_TimeReport("drawtrans");
7449         }
7450
7451         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))
7452         {
7453                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7454                 if (r_timereport_active)
7455                         R_TimeReport("worlddebug");
7456                 R_DrawModelsDebug();
7457                 if (r_timereport_active)
7458                         R_TimeReport("modeldebug");
7459         }
7460
7461         if (cl.csqc_vidvars.drawworld)
7462         {
7463                 R_Shadow_DrawCoronas();
7464                 if (r_timereport_active)
7465                         R_TimeReport("coronas");
7466         }
7467
7468 #if 0
7469         {
7470                 GL_DepthTest(false);
7471                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7472                 GL_Color(1, 1, 1, 1);
7473                 qglBegin(GL_POLYGON);
7474                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7475                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7476                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7477                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7478                 qglEnd();
7479                 qglBegin(GL_POLYGON);
7480                 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]);
7481                 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]);
7482                 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]);
7483                 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]);
7484                 qglEnd();
7485                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7486         }
7487 #endif
7488
7489         // don't let sound skip if going slow
7490         if (r_refdef.scene.extraupdate)
7491                 S_ExtraUpdate ();
7492 }
7493
7494 static const unsigned short bboxelements[36] =
7495 {
7496         5, 1, 3, 5, 3, 7,
7497         6, 2, 0, 6, 0, 4,
7498         7, 3, 2, 7, 2, 6,
7499         4, 0, 1, 4, 1, 5,
7500         4, 5, 7, 4, 7, 6,
7501         1, 0, 2, 1, 2, 3,
7502 };
7503
7504 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7505 {
7506         int i;
7507         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7508
7509         RSurf_ActiveWorldEntity();
7510
7511         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7512         GL_DepthMask(false);
7513         GL_DepthRange(0, 1);
7514         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7515 //      R_Mesh_ResetTextureState();
7516
7517         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7518         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7519         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7520         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7521         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7522         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7523         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7524         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7525         R_FillColors(color4f, 8, cr, cg, cb, ca);
7526         if (r_refdef.fogenabled)
7527         {
7528                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7529                 {
7530                         f1 = RSurf_FogVertex(v);
7531                         f2 = 1 - f1;
7532                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7533                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7534                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7535                 }
7536         }
7537         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7538         R_Mesh_ResetTextureState();
7539         R_SetupShader_Generic_NoTexture(false, false);
7540         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7541 }
7542
7543 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7544 {
7545         prvm_prog_t *prog = SVVM_prog;
7546         int i;
7547         float color[4];
7548         prvm_edict_t *edict;
7549
7550         // this function draws bounding boxes of server entities
7551         if (!sv.active)
7552                 return;
7553
7554         GL_CullFace(GL_NONE);
7555         R_SetupShader_Generic_NoTexture(false, false);
7556
7557         for (i = 0;i < numsurfaces;i++)
7558         {
7559                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7560                 switch ((int)PRVM_serveredictfloat(edict, solid))
7561                 {
7562                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7563                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7564                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7565                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7566                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7567                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7568                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7569                 }
7570                 color[3] *= r_showbboxes.value;
7571                 color[3] = bound(0, color[3], 1);
7572                 GL_DepthTest(!r_showdisabledepthtest.integer);
7573                 GL_CullFace(r_refdef.view.cullface_front);
7574                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7575         }
7576 }
7577
7578 static void R_DrawEntityBBoxes(void)
7579 {
7580         int i;
7581         prvm_edict_t *edict;
7582         vec3_t center;
7583         prvm_prog_t *prog = SVVM_prog;
7584
7585         // this function draws bounding boxes of server entities
7586         if (!sv.active)
7587                 return;
7588
7589         for (i = 0;i < prog->num_edicts;i++)
7590         {
7591                 edict = PRVM_EDICT_NUM(i);
7592                 if (edict->priv.server->free)
7593                         continue;
7594                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7595                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7596                         continue;
7597                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7598                         continue;
7599                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7600                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7601         }
7602 }
7603
7604 static const int nomodelelement3i[24] =
7605 {
7606         5, 2, 0,
7607         5, 1, 2,
7608         5, 0, 3,
7609         5, 3, 1,
7610         0, 2, 4,
7611         2, 1, 4,
7612         3, 0, 4,
7613         1, 3, 4
7614 };
7615
7616 static const unsigned short nomodelelement3s[24] =
7617 {
7618         5, 2, 0,
7619         5, 1, 2,
7620         5, 0, 3,
7621         5, 3, 1,
7622         0, 2, 4,
7623         2, 1, 4,
7624         3, 0, 4,
7625         1, 3, 4
7626 };
7627
7628 static const float nomodelvertex3f[6*3] =
7629 {
7630         -16,   0,   0,
7631          16,   0,   0,
7632           0, -16,   0,
7633           0,  16,   0,
7634           0,   0, -16,
7635           0,   0,  16
7636 };
7637
7638 static const float nomodelcolor4f[6*4] =
7639 {
7640         0.0f, 0.0f, 0.5f, 1.0f,
7641         0.0f, 0.0f, 0.5f, 1.0f,
7642         0.0f, 0.5f, 0.0f, 1.0f,
7643         0.0f, 0.5f, 0.0f, 1.0f,
7644         0.5f, 0.0f, 0.0f, 1.0f,
7645         0.5f, 0.0f, 0.0f, 1.0f
7646 };
7647
7648 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7649 {
7650         int i;
7651         float f1, f2, *c;
7652         float color4f[6*4];
7653
7654         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);
7655
7656         // this is only called once per entity so numsurfaces is always 1, and
7657         // surfacelist is always {0}, so this code does not handle batches
7658
7659         if (rsurface.ent_flags & RENDER_ADDITIVE)
7660         {
7661                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7662                 GL_DepthMask(false);
7663         }
7664         else if (rsurface.colormod[3] < 1)
7665         {
7666                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7667                 GL_DepthMask(false);
7668         }
7669         else
7670         {
7671                 GL_BlendFunc(GL_ONE, GL_ZERO);
7672                 GL_DepthMask(true);
7673         }
7674         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7675         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7676         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7677         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7678         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7679         for (i = 0, c = color4f;i < 6;i++, c += 4)
7680         {
7681                 c[0] *= rsurface.colormod[0];
7682                 c[1] *= rsurface.colormod[1];
7683                 c[2] *= rsurface.colormod[2];
7684                 c[3] *= rsurface.colormod[3];
7685         }
7686         if (r_refdef.fogenabled)
7687         {
7688                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7689                 {
7690                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7691                         f2 = 1 - f1;
7692                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7693                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7694                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7695                 }
7696         }
7697 //      R_Mesh_ResetTextureState();
7698         R_SetupShader_Generic_NoTexture(false, false);
7699         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7700         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7701 }
7702
7703 void R_DrawNoModel(entity_render_t *ent)
7704 {
7705         vec3_t org;
7706         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7707         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7708                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7709         else
7710                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7711 }
7712
7713 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7714 {
7715         vec3_t right1, right2, diff, normal;
7716
7717         VectorSubtract (org2, org1, normal);
7718
7719         // calculate 'right' vector for start
7720         VectorSubtract (r_refdef.view.origin, org1, diff);
7721         CrossProduct (normal, diff, right1);
7722         VectorNormalize (right1);
7723
7724         // calculate 'right' vector for end
7725         VectorSubtract (r_refdef.view.origin, org2, diff);
7726         CrossProduct (normal, diff, right2);
7727         VectorNormalize (right2);
7728
7729         vert[ 0] = org1[0] + width * right1[0];
7730         vert[ 1] = org1[1] + width * right1[1];
7731         vert[ 2] = org1[2] + width * right1[2];
7732         vert[ 3] = org1[0] - width * right1[0];
7733         vert[ 4] = org1[1] - width * right1[1];
7734         vert[ 5] = org1[2] - width * right1[2];
7735         vert[ 6] = org2[0] - width * right2[0];
7736         vert[ 7] = org2[1] - width * right2[1];
7737         vert[ 8] = org2[2] - width * right2[2];
7738         vert[ 9] = org2[0] + width * right2[0];
7739         vert[10] = org2[1] + width * right2[1];
7740         vert[11] = org2[2] + width * right2[2];
7741 }
7742
7743 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)
7744 {
7745         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7746         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7747         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7748         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7749         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7750         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7751         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7752         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7753         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7754         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7755         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7756         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7757 }
7758
7759 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7760 {
7761         int i;
7762         float *vertex3f;
7763         float v[3];
7764         VectorSet(v, x, y, z);
7765         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7766                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7767                         break;
7768         if (i == mesh->numvertices)
7769         {
7770                 if (mesh->numvertices < mesh->maxvertices)
7771                 {
7772                         VectorCopy(v, vertex3f);
7773                         mesh->numvertices++;
7774                 }
7775                 return mesh->numvertices;
7776         }
7777         else
7778                 return i;
7779 }
7780
7781 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7782 {
7783         int i;
7784         int *e, element[3];
7785         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7786         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7787         e = mesh->element3i + mesh->numtriangles * 3;
7788         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7789         {
7790                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7791                 if (mesh->numtriangles < mesh->maxtriangles)
7792                 {
7793                         *e++ = element[0];
7794                         *e++ = element[1];
7795                         *e++ = element[2];
7796                         mesh->numtriangles++;
7797                 }
7798                 element[1] = element[2];
7799         }
7800 }
7801
7802 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7803 {
7804         int i;
7805         int *e, element[3];
7806         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7807         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7808         e = mesh->element3i + mesh->numtriangles * 3;
7809         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7810         {
7811                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7812                 if (mesh->numtriangles < mesh->maxtriangles)
7813                 {
7814                         *e++ = element[0];
7815                         *e++ = element[1];
7816                         *e++ = element[2];
7817                         mesh->numtriangles++;
7818                 }
7819                 element[1] = element[2];
7820         }
7821 }
7822
7823 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7824 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7825 {
7826         int planenum, planenum2;
7827         int w;
7828         int tempnumpoints;
7829         mplane_t *plane, *plane2;
7830         double maxdist;
7831         double temppoints[2][256*3];
7832         // figure out how large a bounding box we need to properly compute this brush
7833         maxdist = 0;
7834         for (w = 0;w < numplanes;w++)
7835                 maxdist = max(maxdist, fabs(planes[w].dist));
7836         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7837         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7838         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7839         {
7840                 w = 0;
7841                 tempnumpoints = 4;
7842                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7843                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7844                 {
7845                         if (planenum2 == planenum)
7846                                 continue;
7847                         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);
7848                         w = !w;
7849                 }
7850                 if (tempnumpoints < 3)
7851                         continue;
7852                 // generate elements forming a triangle fan for this polygon
7853                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7854         }
7855 }
7856
7857 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)
7858 {
7859         texturelayer_t *layer;
7860         layer = t->currentlayers + t->currentnumlayers++;
7861         layer->type = type;
7862         layer->depthmask = depthmask;
7863         layer->blendfunc1 = blendfunc1;
7864         layer->blendfunc2 = blendfunc2;
7865         layer->texture = texture;
7866         layer->texmatrix = *matrix;
7867         layer->color[0] = r;
7868         layer->color[1] = g;
7869         layer->color[2] = b;
7870         layer->color[3] = a;
7871 }
7872
7873 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7874 {
7875         if(parms[0] == 0 && parms[1] == 0)
7876                 return false;
7877         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7878                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7879                         return false;
7880         return true;
7881 }
7882
7883 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7884 {
7885         double index, f;
7886         index = parms[2] + rsurface.shadertime * parms[3];
7887         index -= floor(index);
7888         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7889         {
7890         default:
7891         case Q3WAVEFUNC_NONE:
7892         case Q3WAVEFUNC_NOISE:
7893         case Q3WAVEFUNC_COUNT:
7894                 f = 0;
7895                 break;
7896         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7897         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7898         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7899         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7900         case Q3WAVEFUNC_TRIANGLE:
7901                 index *= 4;
7902                 f = index - floor(index);
7903                 if (index < 1)
7904                 {
7905                         // f = f;
7906                 }
7907                 else if (index < 2)
7908                         f = 1 - f;
7909                 else if (index < 3)
7910                         f = -f;
7911                 else
7912                         f = -(1 - f);
7913                 break;
7914         }
7915         f = parms[0] + parms[1] * f;
7916         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7917                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7918         return (float) f;
7919 }
7920
7921 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7922 {
7923         int w, h, idx;
7924         double f;
7925         double offsetd[2];
7926         float tcmat[12];
7927         matrix4x4_t matrix, temp;
7928         switch(tcmod->tcmod)
7929         {
7930                 case Q3TCMOD_COUNT:
7931                 case Q3TCMOD_NONE:
7932                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7933                                 matrix = r_waterscrollmatrix;
7934                         else
7935                                 matrix = identitymatrix;
7936                         break;
7937                 case Q3TCMOD_ENTITYTRANSLATE:
7938                         // this is used in Q3 to allow the gamecode to control texcoord
7939                         // scrolling on the entity, which is not supported in darkplaces yet.
7940                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7941                         break;
7942                 case Q3TCMOD_ROTATE:
7943                         f = tcmod->parms[0] * rsurface.shadertime;
7944                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7945                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7946                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7947                         break;
7948                 case Q3TCMOD_SCALE:
7949                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7950                         break;
7951                 case Q3TCMOD_SCROLL:
7952                         // extra care is needed because of precision breakdown with large values of time
7953                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7954                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7955                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7956                         break;
7957                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7958                         w = (int) tcmod->parms[0];
7959                         h = (int) tcmod->parms[1];
7960                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7961                         f = f - floor(f);
7962                         idx = (int) floor(f * w * h);
7963                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7964                         break;
7965                 case Q3TCMOD_STRETCH:
7966                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7967                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7968                         break;
7969                 case Q3TCMOD_TRANSFORM:
7970                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7971                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7972                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7973                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7974                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7975                         break;
7976                 case Q3TCMOD_TURBULENT:
7977                         // this is handled in the RSurf_PrepareVertices function
7978                         matrix = identitymatrix;
7979                         break;
7980         }
7981         temp = *texmatrix;
7982         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7983 }
7984
7985 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7986 {
7987         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7988         char name[MAX_QPATH];
7989         skinframe_t *skinframe;
7990         unsigned char pixels[296*194];
7991         strlcpy(cache->name, skinname, sizeof(cache->name));
7992         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7993         if (developer_loading.integer)
7994                 Con_Printf("loading %s\n", name);
7995         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7996         if (!skinframe || !skinframe->base)
7997         {
7998                 unsigned char *f;
7999                 fs_offset_t filesize;
8000                 skinframe = NULL;
8001                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8002                 if (f)
8003                 {
8004                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8005                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8006                         Mem_Free(f);
8007                 }
8008         }
8009         cache->skinframe = skinframe;
8010 }
8011
8012 texture_t *R_GetCurrentTexture(texture_t *t)
8013 {
8014         int i;
8015         const entity_render_t *ent = rsurface.entity;
8016         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8017         q3shaderinfo_layer_tcmod_t *tcmod;
8018
8019         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8020                 return t->currentframe;
8021         t->update_lastrenderframe = r_textureframe;
8022         t->update_lastrenderentity = (void *)ent;
8023
8024         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8025                 t->camera_entity = ent->entitynumber;
8026         else
8027                 t->camera_entity = 0;
8028
8029         // switch to an alternate material if this is a q1bsp animated material
8030         {
8031                 texture_t *texture = t;
8032                 int s = rsurface.ent_skinnum;
8033                 if ((unsigned int)s >= (unsigned int)model->numskins)
8034                         s = 0;
8035                 if (model->skinscenes)
8036                 {
8037                         if (model->skinscenes[s].framecount > 1)
8038                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8039                         else
8040                                 s = model->skinscenes[s].firstframe;
8041                 }
8042                 if (s > 0)
8043                         t = t + s * model->num_surfaces;
8044                 if (t->animated)
8045                 {
8046                         // use an alternate animation if the entity's frame is not 0,
8047                         // and only if the texture has an alternate animation
8048                         if (rsurface.ent_alttextures && t->anim_total[1])
8049                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8050                         else
8051                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8052                 }
8053                 texture->currentframe = t;
8054         }
8055
8056         // update currentskinframe to be a qw skin or animation frame
8057         if (rsurface.ent_qwskin >= 0)
8058         {
8059                 i = rsurface.ent_qwskin;
8060                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8061                 {
8062                         r_qwskincache_size = cl.maxclients;
8063                         if (r_qwskincache)
8064                                 Mem_Free(r_qwskincache);
8065                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8066                 }
8067                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8068                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8069                 t->currentskinframe = r_qwskincache[i].skinframe;
8070                 if (t->currentskinframe == NULL)
8071                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8072         }
8073         else if (t->numskinframes >= 2)
8074                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8075         if (t->backgroundnumskinframes >= 2)
8076                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8077
8078         t->currentmaterialflags = t->basematerialflags;
8079         t->currentalpha = rsurface.colormod[3];
8080         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8081                 t->currentalpha *= r_wateralpha.value;
8082         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8083                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8084         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8085                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8086         if (!(rsurface.ent_flags & RENDER_LIGHT))
8087                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8088         else if (FAKELIGHT_ENABLED)
8089         {
8090                 // no modellight if using fakelight for the map
8091         }
8092         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8093         {
8094                 // pick a model lighting mode
8095                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8096                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8097                 else
8098                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8099         }
8100         if (rsurface.ent_flags & RENDER_ADDITIVE)
8101                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8102         else if (t->currentalpha < 1)
8103                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8104         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8105         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8106                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8107         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8108                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8109         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8110                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8111         if (t->backgroundnumskinframes)
8112                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8113         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8114         {
8115                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8116                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8117         }
8118         else
8119                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8120         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8121         {
8122                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8123                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8124         }
8125         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8126                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8127
8128         // there is no tcmod
8129         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8130         {
8131                 t->currenttexmatrix = r_waterscrollmatrix;
8132                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8133         }
8134         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8135         {
8136                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8137                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8138         }
8139
8140         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8141                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8142         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8143                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8144
8145         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8146         if (t->currentskinframe->qpixels)
8147                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8148         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8149         if (!t->basetexture)
8150                 t->basetexture = r_texture_notexture;
8151         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8152         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8153         t->nmaptexture = t->currentskinframe->nmap;
8154         if (!t->nmaptexture)
8155                 t->nmaptexture = r_texture_blanknormalmap;
8156         t->glosstexture = r_texture_black;
8157         t->glowtexture = t->currentskinframe->glow;
8158         t->fogtexture = t->currentskinframe->fog;
8159         t->reflectmasktexture = t->currentskinframe->reflect;
8160         if (t->backgroundnumskinframes)
8161         {
8162                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8163                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8164                 t->backgroundglosstexture = r_texture_black;
8165                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8166                 if (!t->backgroundnmaptexture)
8167                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8168                 // make sure that if glow is going to be used, both textures are not NULL
8169                 if (!t->backgroundglowtexture && t->glowtexture)
8170                         t->backgroundglowtexture = r_texture_black;
8171                 if (!t->glowtexture && t->backgroundglowtexture)
8172                         t->glowtexture = r_texture_black;
8173         }
8174         else
8175         {
8176                 t->backgroundbasetexture = r_texture_white;
8177                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8178                 t->backgroundglosstexture = r_texture_black;
8179                 t->backgroundglowtexture = NULL;
8180         }
8181         t->specularpower = r_shadow_glossexponent.value;
8182         // TODO: store reference values for these in the texture?
8183         t->specularscale = 0;
8184         if (r_shadow_gloss.integer > 0)
8185         {
8186                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8187                 {
8188                         if (r_shadow_glossintensity.value > 0)
8189                         {
8190                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8191                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8192                                 t->specularscale = r_shadow_glossintensity.value;
8193                         }
8194                 }
8195                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8196                 {
8197                         t->glosstexture = r_texture_white;
8198                         t->backgroundglosstexture = r_texture_white;
8199                         t->specularscale = r_shadow_gloss2intensity.value;
8200                         t->specularpower = r_shadow_gloss2exponent.value;
8201                 }
8202         }
8203         t->specularscale *= t->specularscalemod;
8204         t->specularpower *= t->specularpowermod;
8205         t->rtlightambient = 0;
8206
8207         // lightmaps mode looks bad with dlights using actual texturing, so turn
8208         // off the colormap and glossmap, but leave the normalmap on as it still
8209         // accurately represents the shading involved
8210         if (gl_lightmaps.integer)
8211         {
8212                 t->basetexture = r_texture_grey128;
8213                 t->pantstexture = r_texture_black;
8214                 t->shirttexture = r_texture_black;
8215                 if (gl_lightmaps.integer < 2)
8216                         t->nmaptexture = r_texture_blanknormalmap;
8217                 t->glosstexture = r_texture_black;
8218                 t->glowtexture = NULL;
8219                 t->fogtexture = NULL;
8220                 t->reflectmasktexture = NULL;
8221                 t->backgroundbasetexture = NULL;
8222                 if (gl_lightmaps.integer < 2)
8223                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8224                 t->backgroundglosstexture = r_texture_black;
8225                 t->backgroundglowtexture = NULL;
8226                 t->specularscale = 0;
8227                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8228         }
8229
8230         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8231         VectorClear(t->dlightcolor);
8232         t->currentnumlayers = 0;
8233         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8234         {
8235                 int blendfunc1, blendfunc2;
8236                 qboolean depthmask;
8237                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8238                 {
8239                         blendfunc1 = GL_SRC_ALPHA;
8240                         blendfunc2 = GL_ONE;
8241                 }
8242                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8243                 {
8244                         blendfunc1 = GL_SRC_ALPHA;
8245                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8246                 }
8247                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8248                 {
8249                         blendfunc1 = t->customblendfunc[0];
8250                         blendfunc2 = t->customblendfunc[1];
8251                 }
8252                 else
8253                 {
8254                         blendfunc1 = GL_ONE;
8255                         blendfunc2 = GL_ZERO;
8256                 }
8257                 // don't colormod evilblend textures
8258                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8259                         VectorSet(t->lightmapcolor, 1, 1, 1);
8260                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8261                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8262                 {
8263                         // fullbright is not affected by r_refdef.lightmapintensity
8264                         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]);
8265                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8266                                 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]);
8267                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8268                                 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]);
8269                 }
8270                 else
8271                 {
8272                         vec3_t ambientcolor;
8273                         float colorscale;
8274                         // set the color tint used for lights affecting this surface
8275                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8276                         colorscale = 2;
8277                         // q3bsp has no lightmap updates, so the lightstylevalue that
8278                         // would normally be baked into the lightmap must be
8279                         // applied to the color
8280                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8281                         if (model->type == mod_brushq3)
8282                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8283                         colorscale *= r_refdef.lightmapintensity;
8284                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8285                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8286                         // basic lit geometry
8287                         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]);
8288                         // add pants/shirt if needed
8289                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8290                                 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]);
8291                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8292                                 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]);
8293                         // now add ambient passes if needed
8294                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8295                         {
8296                                 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]);
8297                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8298                                         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]);
8299                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8300                                         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]);
8301                         }
8302                 }
8303                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8304                         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]);
8305                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8306                 {
8307                         // if this is opaque use alpha blend which will darken the earlier
8308                         // passes cheaply.
8309                         //
8310                         // if this is an alpha blended material, all the earlier passes
8311                         // were darkened by fog already, so we only need to add the fog
8312                         // color ontop through the fog mask texture
8313                         //
8314                         // if this is an additive blended material, all the earlier passes
8315                         // were darkened by fog already, and we should not add fog color
8316                         // (because the background was not darkened, there is no fog color
8317                         // that was lost behind it).
8318                         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]);
8319                 }
8320         }
8321
8322         return t->currentframe;
8323 }
8324
8325 rsurfacestate_t rsurface;
8326
8327 void RSurf_ActiveWorldEntity(void)
8328 {
8329         dp_model_t *model = r_refdef.scene.worldmodel;
8330         //if (rsurface.entity == r_refdef.scene.worldentity)
8331         //      return;
8332         rsurface.entity = r_refdef.scene.worldentity;
8333         rsurface.skeleton = NULL;
8334         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8335         rsurface.ent_skinnum = 0;
8336         rsurface.ent_qwskin = -1;
8337         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8338         rsurface.shadertime = r_refdef.scene.time;
8339         rsurface.matrix = identitymatrix;
8340         rsurface.inversematrix = identitymatrix;
8341         rsurface.matrixscale = 1;
8342         rsurface.inversematrixscale = 1;
8343         R_EntityMatrix(&identitymatrix);
8344         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8345         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8346         rsurface.fograngerecip = r_refdef.fograngerecip;
8347         rsurface.fogheightfade = r_refdef.fogheightfade;
8348         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8349         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8350         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8351         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8352         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8353         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8354         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8355         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8356         rsurface.colormod[3] = 1;
8357         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);
8358         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8359         rsurface.frameblend[0].lerp = 1;
8360         rsurface.ent_alttextures = false;
8361         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8362         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8363         rsurface.entityskeletaltransform3x4 = NULL;
8364         rsurface.entityskeletaltransform3x4buffer = NULL;
8365         rsurface.entityskeletaltransform3x4offset = 0;
8366         rsurface.entityskeletaltransform3x4size = 0;;
8367         rsurface.entityskeletalnumtransforms = 0;
8368         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8369         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8370         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8371         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8372         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8373         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8374         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8375         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8376         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8377         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8378         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8379         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8380         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8381         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8382         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8383         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8384         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8385         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8386         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8387         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8388         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8389         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8390         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8391         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8392         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8393         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8394         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8395         rsurface.modelelement3i = model->surfmesh.data_element3i;
8396         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8397         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8398         rsurface.modelelement3s = model->surfmesh.data_element3s;
8399         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8400         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8401         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8402         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8403         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8404         rsurface.modelsurfaces = model->data_surfaces;
8405         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8406         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8407         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8408         rsurface.modelgeneratedvertex = false;
8409         rsurface.batchgeneratedvertex = false;
8410         rsurface.batchfirstvertex = 0;
8411         rsurface.batchnumvertices = 0;
8412         rsurface.batchfirsttriangle = 0;
8413         rsurface.batchnumtriangles = 0;
8414         rsurface.batchvertex3f  = NULL;
8415         rsurface.batchvertex3f_vertexbuffer = NULL;
8416         rsurface.batchvertex3f_bufferoffset = 0;
8417         rsurface.batchsvector3f = NULL;
8418         rsurface.batchsvector3f_vertexbuffer = NULL;
8419         rsurface.batchsvector3f_bufferoffset = 0;
8420         rsurface.batchtvector3f = NULL;
8421         rsurface.batchtvector3f_vertexbuffer = NULL;
8422         rsurface.batchtvector3f_bufferoffset = 0;
8423         rsurface.batchnormal3f  = NULL;
8424         rsurface.batchnormal3f_vertexbuffer = NULL;
8425         rsurface.batchnormal3f_bufferoffset = 0;
8426         rsurface.batchlightmapcolor4f = NULL;
8427         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8428         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8429         rsurface.batchtexcoordtexture2f = NULL;
8430         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8431         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8432         rsurface.batchtexcoordlightmap2f = NULL;
8433         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8434         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8435         rsurface.batchskeletalindex4ub = NULL;
8436         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8437         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8438         rsurface.batchskeletalweight4ub = NULL;
8439         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8440         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8441         rsurface.batchvertexmesh = NULL;
8442         rsurface.batchvertexmesh_vertexbuffer = NULL;
8443         rsurface.batchvertexmesh_bufferoffset = 0;
8444         rsurface.batchelement3i = NULL;
8445         rsurface.batchelement3i_indexbuffer = NULL;
8446         rsurface.batchelement3i_bufferoffset = 0;
8447         rsurface.batchelement3s = NULL;
8448         rsurface.batchelement3s_indexbuffer = NULL;
8449         rsurface.batchelement3s_bufferoffset = 0;
8450         rsurface.passcolor4f = NULL;
8451         rsurface.passcolor4f_vertexbuffer = NULL;
8452         rsurface.passcolor4f_bufferoffset = 0;
8453         rsurface.forcecurrenttextureupdate = false;
8454 }
8455
8456 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8457 {
8458         dp_model_t *model = ent->model;
8459         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8460         //      return;
8461         rsurface.entity = (entity_render_t *)ent;
8462         rsurface.skeleton = ent->skeleton;
8463         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8464         rsurface.ent_skinnum = ent->skinnum;
8465         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;
8466         rsurface.ent_flags = ent->flags;
8467         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8468         rsurface.matrix = ent->matrix;
8469         rsurface.inversematrix = ent->inversematrix;
8470         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8471         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8472         R_EntityMatrix(&rsurface.matrix);
8473         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8474         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8475         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8476         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8477         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8478         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8479         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8480         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8481         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8482         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8483         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8484         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8485         rsurface.colormod[3] = ent->alpha;
8486         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8487         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8488         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8489         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8490         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8491         if (ent->model->brush.submodel && !prepass)
8492         {
8493                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8494                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8495         }
8496         // if the animcache code decided it should use the shader path, skip the deform step
8497         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8498         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8499         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8500         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8501         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8502         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8503         {
8504                 if (ent->animcache_vertex3f)
8505                 {
8506                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8507                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8508                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8509                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8510                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8511                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8512                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8513                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8514                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8515                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8516                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8517                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8518                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8519                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8520                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8521                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8522                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8523                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8524                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8525                 }
8526                 else if (wanttangents)
8527                 {
8528                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8529                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8530                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8531                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8532                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8533                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8534                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8535                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8536                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8537                         rsurface.modelvertexmesh = NULL;
8538                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8539                         rsurface.modelvertexmesh_bufferoffset = 0;
8540                         rsurface.modelvertex3f_vertexbuffer = NULL;
8541                         rsurface.modelvertex3f_bufferoffset = 0;
8542                         rsurface.modelvertex3f_vertexbuffer = 0;
8543                         rsurface.modelvertex3f_bufferoffset = 0;
8544                         rsurface.modelsvector3f_vertexbuffer = 0;
8545                         rsurface.modelsvector3f_bufferoffset = 0;
8546                         rsurface.modeltvector3f_vertexbuffer = 0;
8547                         rsurface.modeltvector3f_bufferoffset = 0;
8548                         rsurface.modelnormal3f_vertexbuffer = 0;
8549                         rsurface.modelnormal3f_bufferoffset = 0;
8550                 }
8551                 else if (wantnormals)
8552                 {
8553                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8554                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8555                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8556                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8557                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8558                         rsurface.modelsvector3f = NULL;
8559                         rsurface.modeltvector3f = NULL;
8560                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8561                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8562                         rsurface.modelvertexmesh = NULL;
8563                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8564                         rsurface.modelvertexmesh_bufferoffset = 0;
8565                         rsurface.modelvertex3f_vertexbuffer = NULL;
8566                         rsurface.modelvertex3f_bufferoffset = 0;
8567                         rsurface.modelvertex3f_vertexbuffer = 0;
8568                         rsurface.modelvertex3f_bufferoffset = 0;
8569                         rsurface.modelsvector3f_vertexbuffer = 0;
8570                         rsurface.modelsvector3f_bufferoffset = 0;
8571                         rsurface.modeltvector3f_vertexbuffer = 0;
8572                         rsurface.modeltvector3f_bufferoffset = 0;
8573                         rsurface.modelnormal3f_vertexbuffer = 0;
8574                         rsurface.modelnormal3f_bufferoffset = 0;
8575                 }
8576                 else
8577                 {
8578                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8579                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8580                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8581                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8582                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8583                         rsurface.modelsvector3f = NULL;
8584                         rsurface.modeltvector3f = NULL;
8585                         rsurface.modelnormal3f = NULL;
8586                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8587                         rsurface.modelvertexmesh = NULL;
8588                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8589                         rsurface.modelvertexmesh_bufferoffset = 0;
8590                         rsurface.modelvertex3f_vertexbuffer = NULL;
8591                         rsurface.modelvertex3f_bufferoffset = 0;
8592                         rsurface.modelvertex3f_vertexbuffer = 0;
8593                         rsurface.modelvertex3f_bufferoffset = 0;
8594                         rsurface.modelsvector3f_vertexbuffer = 0;
8595                         rsurface.modelsvector3f_bufferoffset = 0;
8596                         rsurface.modeltvector3f_vertexbuffer = 0;
8597                         rsurface.modeltvector3f_bufferoffset = 0;
8598                         rsurface.modelnormal3f_vertexbuffer = 0;
8599                         rsurface.modelnormal3f_bufferoffset = 0;
8600                 }
8601                 rsurface.modelgeneratedvertex = true;
8602         }
8603         else
8604         {
8605                 if (rsurface.entityskeletaltransform3x4)
8606                 {
8607                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8608                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8609                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8610                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8611                 }
8612                 else
8613                 {
8614                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8615                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8616                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8617                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8618                 }
8619                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8620                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8621                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8622                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8623                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8624                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8625                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8626                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8627                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8628                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8629                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8630                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8631                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8632                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8633                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8634                 rsurface.modelgeneratedvertex = false;
8635         }
8636         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8637         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8638         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8639         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8640         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8641         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8642         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8643         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8644         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8645         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8646         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8647         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8648         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8649         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8650         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8651         rsurface.modelelement3i = model->surfmesh.data_element3i;
8652         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8653         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8654         rsurface.modelelement3s = model->surfmesh.data_element3s;
8655         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8656         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8657         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8658         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8659         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8660         rsurface.modelsurfaces = model->data_surfaces;
8661         rsurface.batchgeneratedvertex = false;
8662         rsurface.batchfirstvertex = 0;
8663         rsurface.batchnumvertices = 0;
8664         rsurface.batchfirsttriangle = 0;
8665         rsurface.batchnumtriangles = 0;
8666         rsurface.batchvertex3f  = NULL;
8667         rsurface.batchvertex3f_vertexbuffer = NULL;
8668         rsurface.batchvertex3f_bufferoffset = 0;
8669         rsurface.batchsvector3f = NULL;
8670         rsurface.batchsvector3f_vertexbuffer = NULL;
8671         rsurface.batchsvector3f_bufferoffset = 0;
8672         rsurface.batchtvector3f = NULL;
8673         rsurface.batchtvector3f_vertexbuffer = NULL;
8674         rsurface.batchtvector3f_bufferoffset = 0;
8675         rsurface.batchnormal3f  = NULL;
8676         rsurface.batchnormal3f_vertexbuffer = NULL;
8677         rsurface.batchnormal3f_bufferoffset = 0;
8678         rsurface.batchlightmapcolor4f = NULL;
8679         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8680         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8681         rsurface.batchtexcoordtexture2f = NULL;
8682         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8683         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8684         rsurface.batchtexcoordlightmap2f = NULL;
8685         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8686         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8687         rsurface.batchskeletalindex4ub = NULL;
8688         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8689         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8690         rsurface.batchskeletalweight4ub = NULL;
8691         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8692         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8693         rsurface.batchvertexmesh = NULL;
8694         rsurface.batchvertexmesh_vertexbuffer = NULL;
8695         rsurface.batchvertexmesh_bufferoffset = 0;
8696         rsurface.batchelement3i = NULL;
8697         rsurface.batchelement3i_indexbuffer = NULL;
8698         rsurface.batchelement3i_bufferoffset = 0;
8699         rsurface.batchelement3s = NULL;
8700         rsurface.batchelement3s_indexbuffer = NULL;
8701         rsurface.batchelement3s_bufferoffset = 0;
8702         rsurface.passcolor4f = NULL;
8703         rsurface.passcolor4f_vertexbuffer = NULL;
8704         rsurface.passcolor4f_bufferoffset = 0;
8705         rsurface.forcecurrenttextureupdate = false;
8706 }
8707
8708 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)
8709 {
8710         rsurface.entity = r_refdef.scene.worldentity;
8711         rsurface.skeleton = NULL;
8712         rsurface.ent_skinnum = 0;
8713         rsurface.ent_qwskin = -1;
8714         rsurface.ent_flags = entflags;
8715         rsurface.shadertime = r_refdef.scene.time - shadertime;
8716         rsurface.modelnumvertices = numvertices;
8717         rsurface.modelnumtriangles = numtriangles;
8718         rsurface.matrix = *matrix;
8719         rsurface.inversematrix = *inversematrix;
8720         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8721         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8722         R_EntityMatrix(&rsurface.matrix);
8723         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8724         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8725         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8726         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8727         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8728         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8729         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8730         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8731         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8732         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8733         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8734         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8735         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);
8736         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8737         rsurface.frameblend[0].lerp = 1;
8738         rsurface.ent_alttextures = false;
8739         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8740         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8741         rsurface.entityskeletaltransform3x4 = NULL;
8742         rsurface.entityskeletaltransform3x4buffer = NULL;
8743         rsurface.entityskeletaltransform3x4offset = 0;
8744         rsurface.entityskeletaltransform3x4size = 0;
8745         rsurface.entityskeletalnumtransforms = 0;
8746         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8747         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8748         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8749         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8750         if (wanttangents)
8751         {
8752                 rsurface.modelvertex3f = (float *)vertex3f;
8753                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8754                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8755                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8756         }
8757         else if (wantnormals)
8758         {
8759                 rsurface.modelvertex3f = (float *)vertex3f;
8760                 rsurface.modelsvector3f = NULL;
8761                 rsurface.modeltvector3f = NULL;
8762                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8763         }
8764         else
8765         {
8766                 rsurface.modelvertex3f = (float *)vertex3f;
8767                 rsurface.modelsvector3f = NULL;
8768                 rsurface.modeltvector3f = NULL;
8769                 rsurface.modelnormal3f = NULL;
8770         }
8771         rsurface.modelvertexmesh = NULL;
8772         rsurface.modelvertexmesh_vertexbuffer = NULL;
8773         rsurface.modelvertexmesh_bufferoffset = 0;
8774         rsurface.modelvertex3f_vertexbuffer = 0;
8775         rsurface.modelvertex3f_bufferoffset = 0;
8776         rsurface.modelsvector3f_vertexbuffer = 0;
8777         rsurface.modelsvector3f_bufferoffset = 0;
8778         rsurface.modeltvector3f_vertexbuffer = 0;
8779         rsurface.modeltvector3f_bufferoffset = 0;
8780         rsurface.modelnormal3f_vertexbuffer = 0;
8781         rsurface.modelnormal3f_bufferoffset = 0;
8782         rsurface.modelgeneratedvertex = true;
8783         rsurface.modellightmapcolor4f  = (float *)color4f;
8784         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8785         rsurface.modellightmapcolor4f_bufferoffset = 0;
8786         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8787         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8788         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8789         rsurface.modeltexcoordlightmap2f  = NULL;
8790         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8791         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8792         rsurface.modelskeletalindex4ub = NULL;
8793         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8794         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8795         rsurface.modelskeletalweight4ub = NULL;
8796         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8797         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8798         rsurface.modelelement3i = (int *)element3i;
8799         rsurface.modelelement3i_indexbuffer = NULL;
8800         rsurface.modelelement3i_bufferoffset = 0;
8801         rsurface.modelelement3s = (unsigned short *)element3s;
8802         rsurface.modelelement3s_indexbuffer = NULL;
8803         rsurface.modelelement3s_bufferoffset = 0;
8804         rsurface.modellightmapoffsets = NULL;
8805         rsurface.modelsurfaces = NULL;
8806         rsurface.batchgeneratedvertex = false;
8807         rsurface.batchfirstvertex = 0;
8808         rsurface.batchnumvertices = 0;
8809         rsurface.batchfirsttriangle = 0;
8810         rsurface.batchnumtriangles = 0;
8811         rsurface.batchvertex3f  = NULL;
8812         rsurface.batchvertex3f_vertexbuffer = NULL;
8813         rsurface.batchvertex3f_bufferoffset = 0;
8814         rsurface.batchsvector3f = NULL;
8815         rsurface.batchsvector3f_vertexbuffer = NULL;
8816         rsurface.batchsvector3f_bufferoffset = 0;
8817         rsurface.batchtvector3f = NULL;
8818         rsurface.batchtvector3f_vertexbuffer = NULL;
8819         rsurface.batchtvector3f_bufferoffset = 0;
8820         rsurface.batchnormal3f  = NULL;
8821         rsurface.batchnormal3f_vertexbuffer = NULL;
8822         rsurface.batchnormal3f_bufferoffset = 0;
8823         rsurface.batchlightmapcolor4f = NULL;
8824         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8825         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8826         rsurface.batchtexcoordtexture2f = NULL;
8827         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8828         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8829         rsurface.batchtexcoordlightmap2f = NULL;
8830         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8831         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8832         rsurface.batchskeletalindex4ub = NULL;
8833         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8834         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8835         rsurface.batchskeletalweight4ub = NULL;
8836         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8837         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8838         rsurface.batchvertexmesh = NULL;
8839         rsurface.batchvertexmesh_vertexbuffer = NULL;
8840         rsurface.batchvertexmesh_bufferoffset = 0;
8841         rsurface.batchelement3i = NULL;
8842         rsurface.batchelement3i_indexbuffer = NULL;
8843         rsurface.batchelement3i_bufferoffset = 0;
8844         rsurface.batchelement3s = NULL;
8845         rsurface.batchelement3s_indexbuffer = NULL;
8846         rsurface.batchelement3s_bufferoffset = 0;
8847         rsurface.passcolor4f = NULL;
8848         rsurface.passcolor4f_vertexbuffer = NULL;
8849         rsurface.passcolor4f_bufferoffset = 0;
8850         rsurface.forcecurrenttextureupdate = true;
8851
8852         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8853         {
8854                 if ((wantnormals || wanttangents) && !normal3f)
8855                 {
8856                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8857                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8858                 }
8859                 if (wanttangents && !svector3f)
8860                 {
8861                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8862                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8863                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8864                 }
8865         }
8866 }
8867
8868 float RSurf_FogPoint(const float *v)
8869 {
8870         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8871         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8872         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8873         float FogHeightFade = r_refdef.fogheightfade;
8874         float fogfrac;
8875         unsigned int fogmasktableindex;
8876         if (r_refdef.fogplaneviewabove)
8877                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8878         else
8879                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8880         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8881         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8882 }
8883
8884 float RSurf_FogVertex(const float *v)
8885 {
8886         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8887         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8888         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8889         float FogHeightFade = rsurface.fogheightfade;
8890         float fogfrac;
8891         unsigned int fogmasktableindex;
8892         if (r_refdef.fogplaneviewabove)
8893                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8894         else
8895                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8896         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8897         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8898 }
8899
8900 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8901 {
8902         int i;
8903         for (i = 0;i < numelements;i++)
8904                 outelement3i[i] = inelement3i[i] + adjust;
8905 }
8906
8907 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8908 extern cvar_t gl_vbo;
8909 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8910 {
8911         int deformindex;
8912         int firsttriangle;
8913         int numtriangles;
8914         int firstvertex;
8915         int endvertex;
8916         int numvertices;
8917         int surfacefirsttriangle;
8918         int surfacenumtriangles;
8919         int surfacefirstvertex;
8920         int surfaceendvertex;
8921         int surfacenumvertices;
8922         int batchnumsurfaces = texturenumsurfaces;
8923         int batchnumvertices;
8924         int batchnumtriangles;
8925         int needsupdate;
8926         int i, j;
8927         qboolean gaps;
8928         qboolean dynamicvertex;
8929         float amplitude;
8930         float animpos;
8931         float scale;
8932         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8933         float waveparms[4];
8934         unsigned char *ub;
8935         q3shaderinfo_deform_t *deform;
8936         const msurface_t *surface, *firstsurface;
8937         r_vertexmesh_t *vertexmesh;
8938         if (!texturenumsurfaces)
8939                 return;
8940         // find vertex range of this surface batch
8941         gaps = false;
8942         firstsurface = texturesurfacelist[0];
8943         firsttriangle = firstsurface->num_firsttriangle;
8944         batchnumvertices = 0;
8945         batchnumtriangles = 0;
8946         firstvertex = endvertex = firstsurface->num_firstvertex;
8947         for (i = 0;i < texturenumsurfaces;i++)
8948         {
8949                 surface = texturesurfacelist[i];
8950                 if (surface != firstsurface + i)
8951                         gaps = true;
8952                 surfacefirstvertex = surface->num_firstvertex;
8953                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8954                 surfacenumvertices = surface->num_vertices;
8955                 surfacenumtriangles = surface->num_triangles;
8956                 if (firstvertex > surfacefirstvertex)
8957                         firstvertex = surfacefirstvertex;
8958                 if (endvertex < surfaceendvertex)
8959                         endvertex = surfaceendvertex;
8960                 batchnumvertices += surfacenumvertices;
8961                 batchnumtriangles += surfacenumtriangles;
8962         }
8963
8964         r_refdef.stats[r_stat_batch_batches]++;
8965         if (gaps)
8966                 r_refdef.stats[r_stat_batch_withgaps]++;
8967         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8968         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8969         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8970
8971         // we now know the vertex range used, and if there are any gaps in it
8972         rsurface.batchfirstvertex = firstvertex;
8973         rsurface.batchnumvertices = endvertex - firstvertex;
8974         rsurface.batchfirsttriangle = firsttriangle;
8975         rsurface.batchnumtriangles = batchnumtriangles;
8976
8977         // this variable holds flags for which properties have been updated that
8978         // may require regenerating vertexmesh array...
8979         needsupdate = 0;
8980
8981         // check if any dynamic vertex processing must occur
8982         dynamicvertex = false;
8983
8984         // a cvar to force the dynamic vertex path to be taken, for debugging
8985         if (r_batch_debugdynamicvertexpath.integer)
8986         {
8987                 if (!dynamicvertex)
8988                 {
8989                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8990                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8991                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8992                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8993                 }
8994                 dynamicvertex = true;
8995         }
8996
8997         // if there is a chance of animated vertex colors, it's a dynamic batch
8998         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8999         {
9000                 if (!dynamicvertex)
9001                 {
9002                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9003                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9004                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9005                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9006                 }
9007                 dynamicvertex = true;
9008                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9009         }
9010
9011         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9012         {
9013                 switch (deform->deform)
9014                 {
9015                 default:
9016                 case Q3DEFORM_PROJECTIONSHADOW:
9017                 case Q3DEFORM_TEXT0:
9018                 case Q3DEFORM_TEXT1:
9019                 case Q3DEFORM_TEXT2:
9020                 case Q3DEFORM_TEXT3:
9021                 case Q3DEFORM_TEXT4:
9022                 case Q3DEFORM_TEXT5:
9023                 case Q3DEFORM_TEXT6:
9024                 case Q3DEFORM_TEXT7:
9025                 case Q3DEFORM_NONE:
9026                         break;
9027                 case Q3DEFORM_AUTOSPRITE:
9028                         if (!dynamicvertex)
9029                         {
9030                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9031                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9032                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9033                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9034                         }
9035                         dynamicvertex = true;
9036                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9037                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9038                         break;
9039                 case Q3DEFORM_AUTOSPRITE2:
9040                         if (!dynamicvertex)
9041                         {
9042                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9043                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9044                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9045                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9046                         }
9047                         dynamicvertex = true;
9048                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9049                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9050                         break;
9051                 case Q3DEFORM_NORMAL:
9052                         if (!dynamicvertex)
9053                         {
9054                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9055                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9056                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9057                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9058                         }
9059                         dynamicvertex = true;
9060                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9061                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9062                         break;
9063                 case Q3DEFORM_WAVE:
9064                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9065                                 break; // if wavefunc is a nop, ignore this transform
9066                         if (!dynamicvertex)
9067                         {
9068                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9069                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9070                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9071                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9072                         }
9073                         dynamicvertex = true;
9074                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9075                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9076                         break;
9077                 case Q3DEFORM_BULGE:
9078                         if (!dynamicvertex)
9079                         {
9080                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9081                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9082                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9083                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9084                         }
9085                         dynamicvertex = true;
9086                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9087                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9088                         break;
9089                 case Q3DEFORM_MOVE:
9090                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9091                                 break; // if wavefunc is a nop, ignore this transform
9092                         if (!dynamicvertex)
9093                         {
9094                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9095                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9096                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9097                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9098                         }
9099                         dynamicvertex = true;
9100                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9101                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9102                         break;
9103                 }
9104         }
9105         switch(rsurface.texture->tcgen.tcgen)
9106         {
9107         default:
9108         case Q3TCGEN_TEXTURE:
9109                 break;
9110         case Q3TCGEN_LIGHTMAP:
9111                 if (!dynamicvertex)
9112                 {
9113                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9114                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9115                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9116                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9117                 }
9118                 dynamicvertex = true;
9119                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9120                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9121                 break;
9122         case Q3TCGEN_VECTOR:
9123                 if (!dynamicvertex)
9124                 {
9125                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9126                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9127                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9128                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9129                 }
9130                 dynamicvertex = true;
9131                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9132                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9133                 break;
9134         case Q3TCGEN_ENVIRONMENT:
9135                 if (!dynamicvertex)
9136                 {
9137                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9138                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9139                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9140                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9141                 }
9142                 dynamicvertex = true;
9143                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9144                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9145                 break;
9146         }
9147         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9148         {
9149                 if (!dynamicvertex)
9150                 {
9151                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9152                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9153                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9154                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9155                 }
9156                 dynamicvertex = true;
9157                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9158                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9159         }
9160
9161         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9162         {
9163                 if (!dynamicvertex)
9164                 {
9165                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9166                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9167                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9168                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9169                 }
9170                 dynamicvertex = true;
9171                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9172         }
9173
9174         // when the model data has no vertex buffer (dynamic mesh), we need to
9175         // eliminate gaps
9176         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9177                 batchneed |= BATCHNEED_NOGAPS;
9178
9179         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9180         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9181         // we ensure this by treating the vertex batch as dynamic...
9182         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9183         {
9184                 if (!dynamicvertex)
9185                 {
9186                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9187                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9188                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9189                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9190                 }
9191                 dynamicvertex = true;
9192         }
9193
9194         if (dynamicvertex)
9195         {
9196                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9197                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9198                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9199                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9200                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9201                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9202                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9203                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9204         }
9205
9206         // if needsupdate, we have to do a dynamic vertex batch for sure
9207         if (needsupdate & batchneed)
9208         {
9209                 if (!dynamicvertex)
9210                 {
9211                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9212                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9213                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9214                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9215                 }
9216                 dynamicvertex = true;
9217         }
9218
9219         // see if we need to build vertexmesh from arrays
9220         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9221         {
9222                 if (!dynamicvertex)
9223                 {
9224                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9225                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9226                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9227                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9228                 }
9229                 dynamicvertex = true;
9230         }
9231
9232         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9233         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9234                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9235
9236         rsurface.batchvertex3f = rsurface.modelvertex3f;
9237         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9238         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9239         rsurface.batchsvector3f = rsurface.modelsvector3f;
9240         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9241         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9242         rsurface.batchtvector3f = rsurface.modeltvector3f;
9243         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9244         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9245         rsurface.batchnormal3f = rsurface.modelnormal3f;
9246         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9247         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9248         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9249         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9250         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9251         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9252         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9253         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9254         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9255         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9256         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9257         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9258         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9259         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9260         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9261         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9262         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9263         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9264         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9265         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9266         rsurface.batchelement3i = rsurface.modelelement3i;
9267         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9268         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9269         rsurface.batchelement3s = rsurface.modelelement3s;
9270         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9271         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9272         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9273         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9274         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9275         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9276         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9277
9278         // if any dynamic vertex processing has to occur in software, we copy the
9279         // entire surface list together before processing to rebase the vertices
9280         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9281         //
9282         // if any gaps exist and we do not have a static vertex buffer, we have to
9283         // copy the surface list together to avoid wasting upload bandwidth on the
9284         // vertices in the gaps.
9285         //
9286         // if gaps exist and we have a static vertex buffer, we can choose whether
9287         // to combine the index buffer ranges into one dynamic index buffer or
9288         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9289         //
9290         // in many cases the batch is reduced to one draw call.
9291
9292         rsurface.batchmultidraw = false;
9293         rsurface.batchmultidrawnumsurfaces = 0;
9294         rsurface.batchmultidrawsurfacelist = NULL;
9295
9296         if (!dynamicvertex)
9297         {
9298                 // static vertex data, just set pointers...
9299                 rsurface.batchgeneratedvertex = false;
9300                 // if there are gaps, we want to build a combined index buffer,
9301                 // otherwise use the original static buffer with an appropriate offset
9302                 if (gaps)
9303                 {
9304                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9305                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9306                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9307                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9308                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9309                         {
9310                                 rsurface.batchmultidraw = true;
9311                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9312                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9313                                 return;
9314                         }
9315                         // build a new triangle elements array for this batch
9316                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9317                         rsurface.batchfirsttriangle = 0;
9318                         numtriangles = 0;
9319                         for (i = 0;i < texturenumsurfaces;i++)
9320                         {
9321                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9322                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9323                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9324                                 numtriangles += surfacenumtriangles;
9325                         }
9326                         rsurface.batchelement3i_indexbuffer = NULL;
9327                         rsurface.batchelement3i_bufferoffset = 0;
9328                         rsurface.batchelement3s = NULL;
9329                         rsurface.batchelement3s_indexbuffer = NULL;
9330                         rsurface.batchelement3s_bufferoffset = 0;
9331                         if (endvertex <= 65536)
9332                         {
9333                                 // make a 16bit (unsigned short) index array if possible
9334                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9335                                 for (i = 0;i < numtriangles*3;i++)
9336                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9337                         }
9338                         // upload buffer data for the copytriangles batch
9339                         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
9340                         {
9341                                 if (rsurface.batchelement3s)
9342                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
9343                                 else if (rsurface.batchelement3i)
9344                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
9345                         }
9346                 }
9347                 else
9348                 {
9349                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9350                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9351                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9352                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9353                 }
9354                 return;
9355         }
9356
9357         // something needs software processing, do it for real...
9358         // we only directly handle separate array data in this case and then
9359         // generate interleaved data if needed...
9360         rsurface.batchgeneratedvertex = true;
9361         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9362         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9363         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9364         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9365
9366         // now copy the vertex data into a combined array and make an index array
9367         // (this is what Quake3 does all the time)
9368         // we also apply any skeletal animation here that would have been done in
9369         // the vertex shader, because most of the dynamic vertex animation cases
9370         // need actual vertex positions and normals
9371         //if (dynamicvertex)
9372         {
9373                 rsurface.batchvertexmesh = NULL;
9374                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9375                 rsurface.batchvertexmesh_bufferoffset = 0;
9376                 rsurface.batchvertex3f = NULL;
9377                 rsurface.batchvertex3f_vertexbuffer = NULL;
9378                 rsurface.batchvertex3f_bufferoffset = 0;
9379                 rsurface.batchsvector3f = NULL;
9380                 rsurface.batchsvector3f_vertexbuffer = NULL;
9381                 rsurface.batchsvector3f_bufferoffset = 0;
9382                 rsurface.batchtvector3f = NULL;
9383                 rsurface.batchtvector3f_vertexbuffer = NULL;
9384                 rsurface.batchtvector3f_bufferoffset = 0;
9385                 rsurface.batchnormal3f = NULL;
9386                 rsurface.batchnormal3f_vertexbuffer = NULL;
9387                 rsurface.batchnormal3f_bufferoffset = 0;
9388                 rsurface.batchlightmapcolor4f = NULL;
9389                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9390                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9391                 rsurface.batchtexcoordtexture2f = NULL;
9392                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9393                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9394                 rsurface.batchtexcoordlightmap2f = NULL;
9395                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9396                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9397                 rsurface.batchskeletalindex4ub = NULL;
9398                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9399                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9400                 rsurface.batchskeletalweight4ub = NULL;
9401                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9402                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9403                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9404                 rsurface.batchelement3i_indexbuffer = NULL;
9405                 rsurface.batchelement3i_bufferoffset = 0;
9406                 rsurface.batchelement3s = NULL;
9407                 rsurface.batchelement3s_indexbuffer = NULL;
9408                 rsurface.batchelement3s_bufferoffset = 0;
9409                 rsurface.batchskeletaltransform3x4buffer = NULL;
9410                 rsurface.batchskeletaltransform3x4offset = 0;
9411                 rsurface.batchskeletaltransform3x4size = 0;
9412                 // we'll only be setting up certain arrays as needed
9413                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9414                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9415                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9416                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9417                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9418                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9419                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9420                 {
9421                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9422                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9423                 }
9424                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9425                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9426                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9427                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9428                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9429                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9430                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9431                 {
9432                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9433                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9434                 }
9435                 numvertices = 0;
9436                 numtriangles = 0;
9437                 for (i = 0;i < texturenumsurfaces;i++)
9438                 {
9439                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9440                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9441                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9442                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9443                         // copy only the data requested
9444                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9445                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9446                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9447                         {
9448                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9449                                 {
9450                                         if (rsurface.batchvertex3f)
9451                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9452                                         else
9453                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9454                                 }
9455                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9456                                 {
9457                                         if (rsurface.modelnormal3f)
9458                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9459                                         else
9460                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9461                                 }
9462                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9463                                 {
9464                                         if (rsurface.modelsvector3f)
9465                                         {
9466                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9467                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9468                                         }
9469                                         else
9470                                         {
9471                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9472                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9473                                         }
9474                                 }
9475                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9476                                 {
9477                                         if (rsurface.modellightmapcolor4f)
9478                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9479                                         else
9480                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9481                                 }
9482                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9483                                 {
9484                                         if (rsurface.modeltexcoordtexture2f)
9485                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9486                                         else
9487                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9488                                 }
9489                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9490                                 {
9491                                         if (rsurface.modeltexcoordlightmap2f)
9492                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9493                                         else
9494                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9495                                 }
9496                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9497                                 {
9498                                         if (rsurface.modelskeletalindex4ub)
9499                                         {
9500                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9501                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9502                                         }
9503                                         else
9504                                         {
9505                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9506                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9507                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9508                                                 for (j = 0;j < surfacenumvertices;j++)
9509                                                         ub[j*4] = 255;
9510                                         }
9511                                 }
9512                         }
9513                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9514                         numvertices += surfacenumvertices;
9515                         numtriangles += surfacenumtriangles;
9516                 }
9517
9518                 // generate a 16bit index array as well if possible
9519                 // (in general, dynamic batches fit)
9520                 if (numvertices <= 65536)
9521                 {
9522                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9523                         for (i = 0;i < numtriangles*3;i++)
9524                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9525                 }
9526
9527                 // since we've copied everything, the batch now starts at 0
9528                 rsurface.batchfirstvertex = 0;
9529                 rsurface.batchnumvertices = batchnumvertices;
9530                 rsurface.batchfirsttriangle = 0;
9531                 rsurface.batchnumtriangles = batchnumtriangles;
9532         }
9533
9534         // apply skeletal animation that would have been done in the vertex shader
9535         if (rsurface.batchskeletaltransform3x4)
9536         {
9537                 const unsigned char *si;
9538                 const unsigned char *sw;
9539                 const float *t[4];
9540                 const float *b = rsurface.batchskeletaltransform3x4;
9541                 float *vp, *vs, *vt, *vn;
9542                 float w[4];
9543                 float m[3][4], n[3][4];
9544                 float tp[3], ts[3], tt[3], tn[3];
9545                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9546                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9547                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9548                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9549                 si = rsurface.batchskeletalindex4ub;
9550                 sw = rsurface.batchskeletalweight4ub;
9551                 vp = rsurface.batchvertex3f;
9552                 vs = rsurface.batchsvector3f;
9553                 vt = rsurface.batchtvector3f;
9554                 vn = rsurface.batchnormal3f;
9555                 memset(m[0], 0, sizeof(m));
9556                 memset(n[0], 0, sizeof(n));
9557                 for (i = 0;i < batchnumvertices;i++)
9558                 {
9559                         t[0] = b + si[0]*12;
9560                         if (sw[0] == 255)
9561                         {
9562                                 // common case - only one matrix
9563                                 m[0][0] = t[0][ 0];
9564                                 m[0][1] = t[0][ 1];
9565                                 m[0][2] = t[0][ 2];
9566                                 m[0][3] = t[0][ 3];
9567                                 m[1][0] = t[0][ 4];
9568                                 m[1][1] = t[0][ 5];
9569                                 m[1][2] = t[0][ 6];
9570                                 m[1][3] = t[0][ 7];
9571                                 m[2][0] = t[0][ 8];
9572                                 m[2][1] = t[0][ 9];
9573                                 m[2][2] = t[0][10];
9574                                 m[2][3] = t[0][11];
9575                         }
9576                         else if (sw[2] + sw[3])
9577                         {
9578                                 // blend 4 matrices
9579                                 t[1] = b + si[1]*12;
9580                                 t[2] = b + si[2]*12;
9581                                 t[3] = b + si[3]*12;
9582                                 w[0] = sw[0] * (1.0f / 255.0f);
9583                                 w[1] = sw[1] * (1.0f / 255.0f);
9584                                 w[2] = sw[2] * (1.0f / 255.0f);
9585                                 w[3] = sw[3] * (1.0f / 255.0f);
9586                                 // blend the matrices
9587                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9588                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9589                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9590                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9591                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9592                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9593                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9594                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9595                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9596                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9597                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9598                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9599                         }
9600                         else
9601                         {
9602                                 // blend 2 matrices
9603                                 t[1] = b + si[1]*12;
9604                                 w[0] = sw[0] * (1.0f / 255.0f);
9605                                 w[1] = sw[1] * (1.0f / 255.0f);
9606                                 // blend the matrices
9607                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9608                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9609                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9610                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9611                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9612                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9613                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9614                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9615                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9616                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9617                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9618                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9619                         }
9620                         si += 4;
9621                         sw += 4;
9622                         // modify the vertex
9623                         VectorCopy(vp, tp);
9624                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9625                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9626                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9627                         vp += 3;
9628                         if (vn)
9629                         {
9630                                 // the normal transformation matrix is a set of cross products...
9631                                 CrossProduct(m[1], m[2], n[0]);
9632                                 CrossProduct(m[2], m[0], n[1]);
9633                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9634                                 VectorCopy(vn, tn);
9635                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9636                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9637                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9638                                 VectorNormalize(vn);
9639                                 vn += 3;
9640                                 if (vs)
9641                                 {
9642                                         VectorCopy(vs, ts);
9643                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9644                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9645                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9646                                         VectorNormalize(vs);
9647                                         vs += 3;
9648                                         VectorCopy(vt, tt);
9649                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9650                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9651                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9652                                         VectorNormalize(vt);
9653                                         vt += 3;
9654                                 }
9655                         }
9656                 }
9657                 rsurface.batchskeletaltransform3x4 = NULL;
9658                 rsurface.batchskeletalnumtransforms = 0;
9659         }
9660
9661         // q1bsp surfaces rendered in vertex color mode have to have colors
9662         // calculated based on lightstyles
9663         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9664         {
9665                 // generate color arrays for the surfaces in this list
9666                 int c[4];
9667                 int scale;
9668                 int size3;
9669                 const int *offsets;
9670                 const unsigned char *lm;
9671                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9672                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9673                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9674                 numvertices = 0;
9675                 for (i = 0;i < texturenumsurfaces;i++)
9676                 {
9677                         surface = texturesurfacelist[i];
9678                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9679                         surfacenumvertices = surface->num_vertices;
9680                         if (surface->lightmapinfo->samples)
9681                         {
9682                                 for (j = 0;j < surfacenumvertices;j++)
9683                                 {
9684                                         lm = surface->lightmapinfo->samples + offsets[j];
9685                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9686                                         VectorScale(lm, scale, c);
9687                                         if (surface->lightmapinfo->styles[1] != 255)
9688                                         {
9689                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9690                                                 lm += size3;
9691                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9692                                                 VectorMA(c, scale, lm, c);
9693                                                 if (surface->lightmapinfo->styles[2] != 255)
9694                                                 {
9695                                                         lm += size3;
9696                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9697                                                         VectorMA(c, scale, lm, c);
9698                                                         if (surface->lightmapinfo->styles[3] != 255)
9699                                                         {
9700                                                                 lm += size3;
9701                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9702                                                                 VectorMA(c, scale, lm, c);
9703                                                         }
9704                                                 }
9705                                         }
9706                                         c[0] >>= 7;
9707                                         c[1] >>= 7;
9708                                         c[2] >>= 7;
9709                                         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);
9710                                         numvertices++;
9711                                 }
9712                         }
9713                         else
9714                         {
9715                                 for (j = 0;j < surfacenumvertices;j++)
9716                                 {
9717                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9718                                         numvertices++;
9719                                 }
9720                         }
9721                 }
9722         }
9723
9724         // if vertices are deformed (sprite flares and things in maps, possibly
9725         // water waves, bulges and other deformations), modify the copied vertices
9726         // in place
9727         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9728         {
9729                 switch (deform->deform)
9730                 {
9731                 default:
9732                 case Q3DEFORM_PROJECTIONSHADOW:
9733                 case Q3DEFORM_TEXT0:
9734                 case Q3DEFORM_TEXT1:
9735                 case Q3DEFORM_TEXT2:
9736                 case Q3DEFORM_TEXT3:
9737                 case Q3DEFORM_TEXT4:
9738                 case Q3DEFORM_TEXT5:
9739                 case Q3DEFORM_TEXT6:
9740                 case Q3DEFORM_TEXT7:
9741                 case Q3DEFORM_NONE:
9742                         break;
9743                 case Q3DEFORM_AUTOSPRITE:
9744                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9745                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9746                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9747                         VectorNormalize(newforward);
9748                         VectorNormalize(newright);
9749                         VectorNormalize(newup);
9750 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9751 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9752 //                      rsurface.batchvertex3f_bufferoffset = 0;
9753 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9754 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9755 //                      rsurface.batchsvector3f_bufferoffset = 0;
9756 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9757 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9758 //                      rsurface.batchtvector3f_bufferoffset = 0;
9759 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9760 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9761 //                      rsurface.batchnormal3f_bufferoffset = 0;
9762                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9763                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9764                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9765                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9766                                 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);
9767                         // a single autosprite surface can contain multiple sprites...
9768                         for (j = 0;j < batchnumvertices - 3;j += 4)
9769                         {
9770                                 VectorClear(center);
9771                                 for (i = 0;i < 4;i++)
9772                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9773                                 VectorScale(center, 0.25f, center);
9774                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9775                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9776                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9777                                 for (i = 0;i < 4;i++)
9778                                 {
9779                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9780                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9781                                 }
9782                         }
9783                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9784                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9785                         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);
9786                         break;
9787                 case Q3DEFORM_AUTOSPRITE2:
9788                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9789                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9790                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9791                         VectorNormalize(newforward);
9792                         VectorNormalize(newright);
9793                         VectorNormalize(newup);
9794 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9795 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9796 //                      rsurface.batchvertex3f_bufferoffset = 0;
9797                         {
9798                                 const float *v1, *v2;
9799                                 vec3_t start, end;
9800                                 float f, l;
9801                                 struct
9802                                 {
9803                                         float length2;
9804                                         const float *v1;
9805                                         const float *v2;
9806                                 }
9807                                 shortest[2];
9808                                 memset(shortest, 0, sizeof(shortest));
9809                                 // a single autosprite surface can contain multiple sprites...
9810                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9811                                 {
9812                                         VectorClear(center);
9813                                         for (i = 0;i < 4;i++)
9814                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9815                                         VectorScale(center, 0.25f, center);
9816                                         // find the two shortest edges, then use them to define the
9817                                         // axis vectors for rotating around the central axis
9818                                         for (i = 0;i < 6;i++)
9819                                         {
9820                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9821                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9822                                                 l = VectorDistance2(v1, v2);
9823                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9824                                                 if (v1[2] != v2[2])
9825                                                         l += (1.0f / 1024.0f);
9826                                                 if (shortest[0].length2 > l || i == 0)
9827                                                 {
9828                                                         shortest[1] = shortest[0];
9829                                                         shortest[0].length2 = l;
9830                                                         shortest[0].v1 = v1;
9831                                                         shortest[0].v2 = v2;
9832                                                 }
9833                                                 else if (shortest[1].length2 > l || i == 1)
9834                                                 {
9835                                                         shortest[1].length2 = l;
9836                                                         shortest[1].v1 = v1;
9837                                                         shortest[1].v2 = v2;
9838                                                 }
9839                                         }
9840                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9841                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9842                                         // this calculates the right vector from the shortest edge
9843                                         // and the up vector from the edge midpoints
9844                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9845                                         VectorNormalize(right);
9846                                         VectorSubtract(end, start, up);
9847                                         VectorNormalize(up);
9848                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9849                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9850                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9851                                         VectorNegate(forward, forward);
9852                                         VectorReflect(forward, 0, up, forward);
9853                                         VectorNormalize(forward);
9854                                         CrossProduct(up, forward, newright);
9855                                         VectorNormalize(newright);
9856                                         // rotate the quad around the up axis vector, this is made
9857                                         // especially easy by the fact we know the quad is flat,
9858                                         // so we only have to subtract the center position and
9859                                         // measure distance along the right vector, and then
9860                                         // multiply that by the newright vector and add back the
9861                                         // center position
9862                                         // we also need to subtract the old position to undo the
9863                                         // displacement from the center, which we do with a
9864                                         // DotProduct, the subtraction/addition of center is also
9865                                         // optimized into DotProducts here
9866                                         l = DotProduct(right, center);
9867                                         for (i = 0;i < 4;i++)
9868                                         {
9869                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9870                                                 f = DotProduct(right, v1) - l;
9871                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9872                                         }
9873                                 }
9874                         }
9875                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9876                         {
9877 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9878 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9879 //                              rsurface.batchnormal3f_bufferoffset = 0;
9880                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9881                         }
9882                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9883                         {
9884 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9885 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9886 //                              rsurface.batchsvector3f_bufferoffset = 0;
9887 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9888 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9889 //                              rsurface.batchtvector3f_bufferoffset = 0;
9890                                 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);
9891                         }
9892                         break;
9893                 case Q3DEFORM_NORMAL:
9894                         // deform the normals to make reflections wavey
9895                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9896                         rsurface.batchnormal3f_vertexbuffer = NULL;
9897                         rsurface.batchnormal3f_bufferoffset = 0;
9898                         for (j = 0;j < batchnumvertices;j++)
9899                         {
9900                                 float vertex[3];
9901                                 float *normal = rsurface.batchnormal3f + 3*j;
9902                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9903                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9904                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9905                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9906                                 VectorNormalize(normal);
9907                         }
9908                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9909                         {
9910 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9911 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9912 //                              rsurface.batchsvector3f_bufferoffset = 0;
9913 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9914 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9915 //                              rsurface.batchtvector3f_bufferoffset = 0;
9916                                 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);
9917                         }
9918                         break;
9919                 case Q3DEFORM_WAVE:
9920                         // deform vertex array to make wavey water and flags and such
9921                         waveparms[0] = deform->waveparms[0];
9922                         waveparms[1] = deform->waveparms[1];
9923                         waveparms[2] = deform->waveparms[2];
9924                         waveparms[3] = deform->waveparms[3];
9925                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9926                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9927                         // this is how a divisor of vertex influence on deformation
9928                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9929                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9930 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9931 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9932 //                      rsurface.batchvertex3f_bufferoffset = 0;
9933 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9934 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9935 //                      rsurface.batchnormal3f_bufferoffset = 0;
9936                         for (j = 0;j < batchnumvertices;j++)
9937                         {
9938                                 // if the wavefunc depends on time, evaluate it per-vertex
9939                                 if (waveparms[3])
9940                                 {
9941                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9942                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9943                                 }
9944                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9945                         }
9946                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9947                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9948                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9949                         {
9950 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9951 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9952 //                              rsurface.batchsvector3f_bufferoffset = 0;
9953 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9954 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9955 //                              rsurface.batchtvector3f_bufferoffset = 0;
9956                                 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);
9957                         }
9958                         break;
9959                 case Q3DEFORM_BULGE:
9960                         // deform vertex array to make the surface have moving bulges
9961 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9962 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9963 //                      rsurface.batchvertex3f_bufferoffset = 0;
9964 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9965 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9966 //                      rsurface.batchnormal3f_bufferoffset = 0;
9967                         for (j = 0;j < batchnumvertices;j++)
9968                         {
9969                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9970                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9971                         }
9972                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9973                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9974                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9975                         {
9976 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9977 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9978 //                              rsurface.batchsvector3f_bufferoffset = 0;
9979 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9980 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9981 //                              rsurface.batchtvector3f_bufferoffset = 0;
9982                                 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);
9983                         }
9984                         break;
9985                 case Q3DEFORM_MOVE:
9986                         // deform vertex array
9987                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9988                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9989                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9990                         VectorScale(deform->parms, scale, waveparms);
9991 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9992 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9993 //                      rsurface.batchvertex3f_bufferoffset = 0;
9994                         for (j = 0;j < batchnumvertices;j++)
9995                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9996                         break;
9997                 }
9998         }
9999
10000         // generate texcoords based on the chosen texcoord source
10001         switch(rsurface.texture->tcgen.tcgen)
10002         {
10003         default:
10004         case Q3TCGEN_TEXTURE:
10005                 break;
10006         case Q3TCGEN_LIGHTMAP:
10007 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10008 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10009 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10010                 if (rsurface.batchtexcoordlightmap2f)
10011                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10012                 break;
10013         case Q3TCGEN_VECTOR:
10014 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10015 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10016 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10017                 for (j = 0;j < batchnumvertices;j++)
10018                 {
10019                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10020                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10021                 }
10022                 break;
10023         case Q3TCGEN_ENVIRONMENT:
10024                 // make environment reflections using a spheremap
10025                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10026                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10027                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10028                 for (j = 0;j < batchnumvertices;j++)
10029                 {
10030                         // identical to Q3A's method, but executed in worldspace so
10031                         // carried models can be shiny too
10032
10033                         float viewer[3], d, reflected[3], worldreflected[3];
10034
10035                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10036                         // VectorNormalize(viewer);
10037
10038                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10039
10040                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10041                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10042                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10043                         // note: this is proportinal to viewer, so we can normalize later
10044
10045                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10046                         VectorNormalize(worldreflected);
10047
10048                         // note: this sphere map only uses world x and z!
10049                         // so positive and negative y will LOOK THE SAME.
10050                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10051                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10052                 }
10053                 break;
10054         }
10055         // the only tcmod that needs software vertex processing is turbulent, so
10056         // check for it here and apply the changes if needed
10057         // and we only support that as the first one
10058         // (handling a mixture of turbulent and other tcmods would be problematic
10059         //  without punting it entirely to a software path)
10060         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10061         {
10062                 amplitude = rsurface.texture->tcmods[0].parms[1];
10063                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10064 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10065 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10066 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10067                 for (j = 0;j < batchnumvertices;j++)
10068                 {
10069                         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);
10070                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10071                 }
10072         }
10073
10074         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10075         {
10076                 // convert the modified arrays to vertex structs
10077 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10078 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10079 //              rsurface.batchvertexmesh_bufferoffset = 0;
10080                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10081                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10082                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10083                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10084                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10085                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10086                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10087                 {
10088                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10089                         {
10090                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10091                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10092                         }
10093                 }
10094                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10095                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10096                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10097                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10098                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10099                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10100                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10101                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10102                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10103                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10104                 {
10105                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10106                         {
10107                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10108                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10109                         }
10110                 }
10111         }
10112
10113         // upload buffer data for the dynamic batch
10114         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
10115         {
10116                 if (rsurface.batchvertexmesh)
10117                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset, !vid.forcevbo);
10118                 else
10119                 {
10120                         if (rsurface.batchvertex3f)
10121                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset, !vid.forcevbo);
10122                         if (rsurface.batchsvector3f)
10123                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset, !vid.forcevbo);
10124                         if (rsurface.batchtvector3f)
10125                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset, !vid.forcevbo);
10126                         if (rsurface.batchnormal3f)
10127                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset, !vid.forcevbo);
10128                         if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10129                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset, !vid.forcevbo);
10130                         if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10131                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset, !vid.forcevbo);
10132                         if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10133                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset, !vid.forcevbo);
10134                         if (rsurface.batchskeletalindex4ub)
10135                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset, !vid.forcevbo);
10136                         if (rsurface.batchskeletalweight4ub)
10137                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset, !vid.forcevbo);
10138                 }
10139                 if (rsurface.batchelement3s)
10140                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
10141                 else if (rsurface.batchelement3i)
10142                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
10143         }
10144 }
10145
10146 void RSurf_DrawBatch(void)
10147 {
10148         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10149         // through the pipeline, killing it earlier in the pipeline would have
10150         // per-surface overhead rather than per-batch overhead, so it's best to
10151         // reject it here, before it hits glDraw.
10152         if (rsurface.batchnumtriangles == 0)
10153                 return;
10154 #if 0
10155         // batch debugging code
10156         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10157         {
10158                 int i;
10159                 int j;
10160                 int c;
10161                 const int *e;
10162                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10163                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10164                 {
10165                         c = e[i];
10166                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10167                         {
10168                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10169                                 {
10170                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10171                                                 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);
10172                                         break;
10173                                 }
10174                         }
10175                 }
10176         }
10177 #endif
10178         if (rsurface.batchmultidraw)
10179         {
10180                 // issue multiple draws rather than copying index data
10181                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10182                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10183                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10184                 for (i = 0;i < numsurfaces;)
10185                 {
10186                         // combine consecutive surfaces as one draw
10187                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10188                                 if (surfacelist[j] != surfacelist[k] + 1)
10189                                         break;
10190                         firstvertex = surfacelist[i]->num_firstvertex;
10191                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10192                         firsttriangle = surfacelist[i]->num_firsttriangle;
10193                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10194                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10195                         i = j;
10196                 }
10197         }
10198         else
10199         {
10200                 // there is only one consecutive run of index data (may have been combined)
10201                 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);
10202         }
10203 }
10204
10205 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10206 {
10207         // pick the closest matching water plane
10208         int planeindex, vertexindex, bestplaneindex = -1;
10209         float d, bestd;
10210         vec3_t vert;
10211         const float *v;
10212         r_waterstate_waterplane_t *p;
10213         qboolean prepared = false;
10214         bestd = 0;
10215         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10216         {
10217                 if(p->camera_entity != rsurface.texture->camera_entity)
10218                         continue;
10219                 d = 0;
10220                 if(!prepared)
10221                 {
10222                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10223                         prepared = true;
10224                         if(rsurface.batchnumvertices == 0)
10225                                 break;
10226                 }
10227                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10228                 {
10229                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10230                         d += fabs(PlaneDiff(vert, &p->plane));
10231                 }
10232                 if (bestd > d || bestplaneindex < 0)
10233                 {
10234                         bestd = d;
10235                         bestplaneindex = planeindex;
10236                 }
10237         }
10238         return bestplaneindex;
10239         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10240         // this situation though, as it might be better to render single larger
10241         // batches with useless stuff (backface culled for example) than to
10242         // render multiple smaller batches
10243 }
10244
10245 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10246 {
10247         int i;
10248         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10249         rsurface.passcolor4f_vertexbuffer = 0;
10250         rsurface.passcolor4f_bufferoffset = 0;
10251         for (i = 0;i < rsurface.batchnumvertices;i++)
10252                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10253 }
10254
10255 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10256 {
10257         int i;
10258         float f;
10259         const float *v;
10260         const float *c;
10261         float *c2;
10262         if (rsurface.passcolor4f)
10263         {
10264                 // generate color arrays
10265                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10266                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10267                 rsurface.passcolor4f_vertexbuffer = 0;
10268                 rsurface.passcolor4f_bufferoffset = 0;
10269                 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)
10270                 {
10271                         f = RSurf_FogVertex(v);
10272                         c2[0] = c[0] * f;
10273                         c2[1] = c[1] * f;
10274                         c2[2] = c[2] * f;
10275                         c2[3] = c[3];
10276                 }
10277         }
10278         else
10279         {
10280                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10281                 rsurface.passcolor4f_vertexbuffer = 0;
10282                 rsurface.passcolor4f_bufferoffset = 0;
10283                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10284                 {
10285                         f = RSurf_FogVertex(v);
10286                         c2[0] = f;
10287                         c2[1] = f;
10288                         c2[2] = f;
10289                         c2[3] = 1;
10290                 }
10291         }
10292 }
10293
10294 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10295 {
10296         int i;
10297         float f;
10298         const float *v;
10299         const float *c;
10300         float *c2;
10301         if (!rsurface.passcolor4f)
10302                 return;
10303         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10304         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10305         rsurface.passcolor4f_vertexbuffer = 0;
10306         rsurface.passcolor4f_bufferoffset = 0;
10307         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)
10308         {
10309                 f = RSurf_FogVertex(v);
10310                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10311                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10312                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10313                 c2[3] = c[3];
10314         }
10315 }
10316
10317 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10318 {
10319         int i;
10320         const float *c;
10321         float *c2;
10322         if (!rsurface.passcolor4f)
10323                 return;
10324         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10325         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10326         rsurface.passcolor4f_vertexbuffer = 0;
10327         rsurface.passcolor4f_bufferoffset = 0;
10328         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10329         {
10330                 c2[0] = c[0] * r;
10331                 c2[1] = c[1] * g;
10332                 c2[2] = c[2] * b;
10333                 c2[3] = c[3] * a;
10334         }
10335 }
10336
10337 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10338 {
10339         int i;
10340         const float *c;
10341         float *c2;
10342         if (!rsurface.passcolor4f)
10343                 return;
10344         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10345         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10346         rsurface.passcolor4f_vertexbuffer = 0;
10347         rsurface.passcolor4f_bufferoffset = 0;
10348         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10349         {
10350                 c2[0] = c[0] + r_refdef.scene.ambient;
10351                 c2[1] = c[1] + r_refdef.scene.ambient;
10352                 c2[2] = c[2] + r_refdef.scene.ambient;
10353                 c2[3] = c[3];
10354         }
10355 }
10356
10357 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10358 {
10359         // TODO: optimize
10360         rsurface.passcolor4f = NULL;
10361         rsurface.passcolor4f_vertexbuffer = 0;
10362         rsurface.passcolor4f_bufferoffset = 0;
10363         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10364         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10365         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10366         GL_Color(r, g, b, a);
10367         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10368         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10369         R_Mesh_TexMatrix(0, NULL);
10370         RSurf_DrawBatch();
10371 }
10372
10373 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10374 {
10375         // TODO: optimize applyfog && applycolor case
10376         // just apply fog if necessary, and tint the fog color array if necessary
10377         rsurface.passcolor4f = NULL;
10378         rsurface.passcolor4f_vertexbuffer = 0;
10379         rsurface.passcolor4f_bufferoffset = 0;
10380         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10381         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10382         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10383         GL_Color(r, g, b, a);
10384         RSurf_DrawBatch();
10385 }
10386
10387 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10388 {
10389         // TODO: optimize
10390         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10391         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10392         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10393         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10394         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10395         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10396         GL_Color(r, g, b, a);
10397         RSurf_DrawBatch();
10398 }
10399
10400 static void RSurf_DrawBatch_GL11_ClampColor(void)
10401 {
10402         int i;
10403         const float *c1;
10404         float *c2;
10405         if (!rsurface.passcolor4f)
10406                 return;
10407         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10408         {
10409                 c2[0] = bound(0.0f, c1[0], 1.0f);
10410                 c2[1] = bound(0.0f, c1[1], 1.0f);
10411                 c2[2] = bound(0.0f, c1[2], 1.0f);
10412                 c2[3] = bound(0.0f, c1[3], 1.0f);
10413         }
10414 }
10415
10416 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10417 {
10418         int i;
10419         float f;
10420         const float *v;
10421         const float *n;
10422         float *c;
10423         //vec3_t eyedir;
10424
10425         // fake shading
10426         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10427         rsurface.passcolor4f_vertexbuffer = 0;
10428         rsurface.passcolor4f_bufferoffset = 0;
10429         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)
10430         {
10431                 f = -DotProduct(r_refdef.view.forward, n);
10432                 f = max(0, f);
10433                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10434                 f *= r_refdef.lightmapintensity;
10435                 Vector4Set(c, f, f, f, 1);
10436         }
10437 }
10438
10439 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10440 {
10441         RSurf_DrawBatch_GL11_ApplyFakeLight();
10442         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10443         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10444         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10445         GL_Color(r, g, b, a);
10446         RSurf_DrawBatch();
10447 }
10448
10449 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10450 {
10451         int i;
10452         float f;
10453         float alpha;
10454         const float *v;
10455         const float *n;
10456         float *c;
10457         vec3_t ambientcolor;
10458         vec3_t diffusecolor;
10459         vec3_t lightdir;
10460         // TODO: optimize
10461         // model lighting
10462         VectorCopy(rsurface.modellight_lightdir, lightdir);
10463         f = 0.5f * r_refdef.lightmapintensity;
10464         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10465         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10466         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10467         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10468         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10469         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10470         alpha = *a;
10471         if (VectorLength2(diffusecolor) > 0)
10472         {
10473                 // q3-style directional shading
10474                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10475                 rsurface.passcolor4f_vertexbuffer = 0;
10476                 rsurface.passcolor4f_bufferoffset = 0;
10477                 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)
10478                 {
10479                         if ((f = DotProduct(n, lightdir)) > 0)
10480                                 VectorMA(ambientcolor, f, diffusecolor, c);
10481                         else
10482                                 VectorCopy(ambientcolor, c);
10483                         c[3] = alpha;
10484                 }
10485                 *r = 1;
10486                 *g = 1;
10487                 *b = 1;
10488                 *a = 1;
10489                 *applycolor = false;
10490         }
10491         else
10492         {
10493                 *r = ambientcolor[0];
10494                 *g = ambientcolor[1];
10495                 *b = ambientcolor[2];
10496                 rsurface.passcolor4f = NULL;
10497                 rsurface.passcolor4f_vertexbuffer = 0;
10498                 rsurface.passcolor4f_bufferoffset = 0;
10499         }
10500 }
10501
10502 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10503 {
10504         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10505         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10506         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10507         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10508         GL_Color(r, g, b, a);
10509         RSurf_DrawBatch();
10510 }
10511
10512 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10513 {
10514         int i;
10515         float f;
10516         const float *v;
10517         float *c;
10518
10519         // fake shading
10520         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10521         rsurface.passcolor4f_vertexbuffer = 0;
10522         rsurface.passcolor4f_bufferoffset = 0;
10523
10524         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10525         {
10526                 f = 1 - RSurf_FogVertex(v);
10527                 c[0] = r;
10528                 c[1] = g;
10529                 c[2] = b;
10530                 c[3] = f * a;
10531         }
10532 }
10533
10534 void RSurf_SetupDepthAndCulling(void)
10535 {
10536         // submodels are biased to avoid z-fighting with world surfaces that they
10537         // may be exactly overlapping (avoids z-fighting artifacts on certain
10538         // doors and things in Quake maps)
10539         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10540         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10541         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10542         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10543 }
10544
10545 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10546 {
10547         // transparent sky would be ridiculous
10548         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10549                 return;
10550         R_SetupShader_Generic_NoTexture(false, false);
10551         skyrenderlater = true;
10552         RSurf_SetupDepthAndCulling();
10553         GL_DepthMask(true);
10554         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10555         // skymasking on them, and Quake3 never did sky masking (unlike
10556         // software Quake and software Quake2), so disable the sky masking
10557         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10558         // and skymasking also looks very bad when noclipping outside the
10559         // level, so don't use it then either.
10560         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10561         {
10562                 R_Mesh_ResetTextureState();
10563                 if (skyrendermasked)
10564                 {
10565                         R_SetupShader_DepthOrShadow(false, false, false);
10566                         // depth-only (masking)
10567                         GL_ColorMask(0,0,0,0);
10568                         // just to make sure that braindead drivers don't draw
10569                         // anything despite that colormask...
10570                         GL_BlendFunc(GL_ZERO, GL_ONE);
10571                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10572                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10573                 }
10574                 else
10575                 {
10576                         R_SetupShader_Generic_NoTexture(false, false);
10577                         // fog sky
10578                         GL_BlendFunc(GL_ONE, GL_ZERO);
10579                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10580                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10581                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10582                 }
10583                 RSurf_DrawBatch();
10584                 if (skyrendermasked)
10585                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10586         }
10587         R_Mesh_ResetTextureState();
10588         GL_Color(1, 1, 1, 1);
10589 }
10590
10591 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10592 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10593 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10594 {
10595         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10596                 return;
10597         if (prepass)
10598         {
10599                 // render screenspace normalmap to texture
10600                 GL_DepthMask(true);
10601                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10602                 RSurf_DrawBatch();
10603                 return;
10604         }
10605
10606         // bind lightmap texture
10607
10608         // water/refraction/reflection/camera surfaces have to be handled specially
10609         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10610         {
10611                 int start, end, startplaneindex;
10612                 for (start = 0;start < texturenumsurfaces;start = end)
10613                 {
10614                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10615                         if(startplaneindex < 0)
10616                         {
10617                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10618                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10619                                 end = start + 1;
10620                                 continue;
10621                         }
10622                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10623                                 ;
10624                         // now that we have a batch using the same planeindex, render it
10625                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10626                         {
10627                                 // render water or distortion background
10628                                 GL_DepthMask(true);
10629                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10630                                 RSurf_DrawBatch();
10631                                 // blend surface on top
10632                                 GL_DepthMask(false);
10633                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10634                                 RSurf_DrawBatch();
10635                         }
10636                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10637                         {
10638                                 // render surface with reflection texture as input
10639                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10640                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10641                                 RSurf_DrawBatch();
10642                         }
10643                 }
10644                 return;
10645         }
10646
10647         // render surface batch normally
10648         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10649         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10650         RSurf_DrawBatch();
10651 }
10652
10653 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10654 {
10655         // OpenGL 1.3 path - anything not completely ancient
10656         qboolean applycolor;
10657         qboolean applyfog;
10658         int layerindex;
10659         const texturelayer_t *layer;
10660         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);
10661         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10662
10663         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10664         {
10665                 vec4_t layercolor;
10666                 int layertexrgbscale;
10667                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10668                 {
10669                         if (layerindex == 0)
10670                                 GL_AlphaTest(true);
10671                         else
10672                         {
10673                                 GL_AlphaTest(false);
10674                                 GL_DepthFunc(GL_EQUAL);
10675                         }
10676                 }
10677                 GL_DepthMask(layer->depthmask && writedepth);
10678                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10679                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10680                 {
10681                         layertexrgbscale = 4;
10682                         VectorScale(layer->color, 0.25f, layercolor);
10683                 }
10684                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10685                 {
10686                         layertexrgbscale = 2;
10687                         VectorScale(layer->color, 0.5f, layercolor);
10688                 }
10689                 else
10690                 {
10691                         layertexrgbscale = 1;
10692                         VectorScale(layer->color, 1.0f, layercolor);
10693                 }
10694                 layercolor[3] = layer->color[3];
10695                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10696                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10697                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10698                 switch (layer->type)
10699                 {
10700                 case TEXTURELAYERTYPE_LITTEXTURE:
10701                         // single-pass lightmapped texture with 2x rgbscale
10702                         R_Mesh_TexBind(0, r_texture_white);
10703                         R_Mesh_TexMatrix(0, NULL);
10704                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10705                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10706                         R_Mesh_TexBind(1, layer->texture);
10707                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10708                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10709                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10710                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10711                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10712                         else if (FAKELIGHT_ENABLED)
10713                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10714                         else if (rsurface.uselightmaptexture)
10715                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10716                         else
10717                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10718                         break;
10719                 case TEXTURELAYERTYPE_TEXTURE:
10720                         // singletexture unlit texture with transparency support
10721                         R_Mesh_TexBind(0, layer->texture);
10722                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10723                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10724                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10725                         R_Mesh_TexBind(1, 0);
10726                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10727                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10728                         break;
10729                 case TEXTURELAYERTYPE_FOG:
10730                         // singletexture fogging
10731                         if (layer->texture)
10732                         {
10733                                 R_Mesh_TexBind(0, layer->texture);
10734                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10735                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10736                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10737                         }
10738                         else
10739                         {
10740                                 R_Mesh_TexBind(0, 0);
10741                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10742                         }
10743                         R_Mesh_TexBind(1, 0);
10744                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10745                         // generate a color array for the fog pass
10746                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10747                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10748                         RSurf_DrawBatch();
10749                         break;
10750                 default:
10751                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10752                 }
10753         }
10754         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10755         {
10756                 GL_DepthFunc(GL_LEQUAL);
10757                 GL_AlphaTest(false);
10758         }
10759 }
10760
10761 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10762 {
10763         // OpenGL 1.1 - crusty old voodoo path
10764         qboolean applyfog;
10765         int layerindex;
10766         const texturelayer_t *layer;
10767         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);
10768         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10769
10770         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10771         {
10772                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10773                 {
10774                         if (layerindex == 0)
10775                                 GL_AlphaTest(true);
10776                         else
10777                         {
10778                                 GL_AlphaTest(false);
10779                                 GL_DepthFunc(GL_EQUAL);
10780                         }
10781                 }
10782                 GL_DepthMask(layer->depthmask && writedepth);
10783                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10784                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10785                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10786                 switch (layer->type)
10787                 {
10788                 case TEXTURELAYERTYPE_LITTEXTURE:
10789                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10790                         {
10791                                 // two-pass lit texture with 2x rgbscale
10792                                 // first the lightmap pass
10793                                 R_Mesh_TexBind(0, r_texture_white);
10794                                 R_Mesh_TexMatrix(0, NULL);
10795                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10796                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10797                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10798                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10799                                 else if (FAKELIGHT_ENABLED)
10800                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10801                                 else if (rsurface.uselightmaptexture)
10802                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10803                                 else
10804                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10805                                 // then apply the texture to it
10806                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10807                                 R_Mesh_TexBind(0, layer->texture);
10808                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10809                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10810                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10811                                 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);
10812                         }
10813                         else
10814                         {
10815                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10816                                 R_Mesh_TexBind(0, layer->texture);
10817                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10818                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10819                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10820                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10821                                         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);
10822                                 else if (FAKELIGHT_ENABLED)
10823                                         RSurf_DrawBatch_GL11_FakeLight(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);
10824                                 else
10825                                         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);
10826                         }
10827                         break;
10828                 case TEXTURELAYERTYPE_TEXTURE:
10829                         // singletexture unlit texture with transparency support
10830                         R_Mesh_TexBind(0, layer->texture);
10831                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10832                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10834                         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);
10835                         break;
10836                 case TEXTURELAYERTYPE_FOG:
10837                         // singletexture fogging
10838                         if (layer->texture)
10839                         {
10840                                 R_Mesh_TexBind(0, layer->texture);
10841                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10842                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10843                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10844                         }
10845                         else
10846                         {
10847                                 R_Mesh_TexBind(0, 0);
10848                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10849                         }
10850                         // generate a color array for the fog pass
10851                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10852                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10853                         RSurf_DrawBatch();
10854                         break;
10855                 default:
10856                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10857                 }
10858         }
10859         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10860         {
10861                 GL_DepthFunc(GL_LEQUAL);
10862                 GL_AlphaTest(false);
10863         }
10864 }
10865
10866 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10867 {
10868         int vi;
10869         int j;
10870         r_vertexgeneric_t *batchvertex;
10871         float c[4];
10872
10873 //      R_Mesh_ResetTextureState();
10874         R_SetupShader_Generic_NoTexture(false, false);
10875
10876         if(rsurface.texture && rsurface.texture->currentskinframe)
10877         {
10878                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10879                 c[3] *= rsurface.texture->currentalpha;
10880         }
10881         else
10882         {
10883                 c[0] = 1;
10884                 c[1] = 0;
10885                 c[2] = 1;
10886                 c[3] = 1;
10887         }
10888
10889         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10890         {
10891                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10892                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10893                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10894         }
10895
10896         // brighten it up (as texture value 127 means "unlit")
10897         c[0] *= 2 * r_refdef.view.colorscale;
10898         c[1] *= 2 * r_refdef.view.colorscale;
10899         c[2] *= 2 * r_refdef.view.colorscale;
10900
10901         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10902                 c[3] *= r_wateralpha.value;
10903
10904         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10905         {
10906                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10907                 GL_DepthMask(false);
10908         }
10909         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10910         {
10911                 GL_BlendFunc(GL_ONE, GL_ONE);
10912                 GL_DepthMask(false);
10913         }
10914         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10915         {
10916                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10917                 GL_DepthMask(false);
10918         }
10919         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10920         {
10921                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10922                 GL_DepthMask(false);
10923         }
10924         else
10925         {
10926                 GL_BlendFunc(GL_ONE, GL_ZERO);
10927                 GL_DepthMask(writedepth);
10928         }
10929
10930         if (r_showsurfaces.integer == 3)
10931         {
10932                 rsurface.passcolor4f = NULL;
10933
10934                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10935                 {
10936                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10937
10938                         rsurface.passcolor4f = NULL;
10939                         rsurface.passcolor4f_vertexbuffer = 0;
10940                         rsurface.passcolor4f_bufferoffset = 0;
10941                 }
10942                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10943                 {
10944                         qboolean applycolor = true;
10945                         float one = 1.0;
10946
10947                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10948
10949                         r_refdef.lightmapintensity = 1;
10950                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10951                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10952                 }
10953                 else if (FAKELIGHT_ENABLED)
10954                 {
10955                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10956
10957                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10958                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10959                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10960                 }
10961                 else
10962                 {
10963                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10964
10965                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10966                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10967                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10968                 }
10969
10970                 if(!rsurface.passcolor4f)
10971                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10972
10973                 RSurf_DrawBatch_GL11_ApplyAmbient();
10974                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10975                 if(r_refdef.fogenabled)
10976                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10977                 RSurf_DrawBatch_GL11_ClampColor();
10978
10979                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10980                 R_SetupShader_Generic_NoTexture(false, false);
10981                 RSurf_DrawBatch();
10982         }
10983         else if (!r_refdef.view.showdebug)
10984         {
10985                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10986                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10987                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10988                 {
10989                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10990                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10991                 }
10992                 R_Mesh_PrepareVertices_Generic_Unlock();
10993                 RSurf_DrawBatch();
10994         }
10995         else if (r_showsurfaces.integer == 4)
10996         {
10997                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10998                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10999                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11000                 {
11001                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11002                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11003                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11004                 }
11005                 R_Mesh_PrepareVertices_Generic_Unlock();
11006                 RSurf_DrawBatch();
11007         }
11008         else if (r_showsurfaces.integer == 2)
11009         {
11010                 const int *e;
11011                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11012                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11013                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11014                 {
11015                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11016                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11017                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11018                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11019                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11020                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11021                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11022                 }
11023                 R_Mesh_PrepareVertices_Generic_Unlock();
11024                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11025         }
11026         else
11027         {
11028                 int texturesurfaceindex;
11029                 int k;
11030                 const msurface_t *surface;
11031                 float surfacecolor4f[4];
11032                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11033                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11034                 vi = 0;
11035                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11036                 {
11037                         surface = texturesurfacelist[texturesurfaceindex];
11038                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11039                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11040                         for (j = 0;j < surface->num_vertices;j++)
11041                         {
11042                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11043                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11044                                 vi++;
11045                         }
11046                 }
11047                 R_Mesh_PrepareVertices_Generic_Unlock();
11048                 RSurf_DrawBatch();
11049         }
11050 }
11051
11052 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11053 {
11054         CHECKGLERROR
11055         RSurf_SetupDepthAndCulling();
11056         if (r_showsurfaces.integer)
11057         {
11058                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11059                 return;
11060         }
11061         switch (vid.renderpath)
11062         {
11063         case RENDERPATH_GL20:
11064         case RENDERPATH_D3D9:
11065         case RENDERPATH_D3D10:
11066         case RENDERPATH_D3D11:
11067         case RENDERPATH_SOFT:
11068         case RENDERPATH_GLES2:
11069                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11070                 break;
11071         case RENDERPATH_GL13:
11072         case RENDERPATH_GLES1:
11073                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11074                 break;
11075         case RENDERPATH_GL11:
11076                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11077                 break;
11078         }
11079         CHECKGLERROR
11080 }
11081
11082 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11083 {
11084         CHECKGLERROR
11085         RSurf_SetupDepthAndCulling();
11086         if (r_showsurfaces.integer)
11087         {
11088                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11089                 return;
11090         }
11091         switch (vid.renderpath)
11092         {
11093         case RENDERPATH_GL20:
11094         case RENDERPATH_D3D9:
11095         case RENDERPATH_D3D10:
11096         case RENDERPATH_D3D11:
11097         case RENDERPATH_SOFT:
11098         case RENDERPATH_GLES2:
11099                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11100                 break;
11101         case RENDERPATH_GL13:
11102         case RENDERPATH_GLES1:
11103                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11104                 break;
11105         case RENDERPATH_GL11:
11106                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11107                 break;
11108         }
11109         CHECKGLERROR
11110 }
11111
11112 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11113 {
11114         int i, j;
11115         int texturenumsurfaces, endsurface;
11116         texture_t *texture;
11117         const msurface_t *surface;
11118         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11119
11120         // if the model is static it doesn't matter what value we give for
11121         // wantnormals and wanttangents, so this logic uses only rules applicable
11122         // to a model, knowing that they are meaningless otherwise
11123         if (ent == r_refdef.scene.worldentity)
11124                 RSurf_ActiveWorldEntity();
11125         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11126                 RSurf_ActiveModelEntity(ent, false, false, false);
11127         else
11128         {
11129                 switch (vid.renderpath)
11130                 {
11131                 case RENDERPATH_GL20:
11132                 case RENDERPATH_D3D9:
11133                 case RENDERPATH_D3D10:
11134                 case RENDERPATH_D3D11:
11135                 case RENDERPATH_SOFT:
11136                 case RENDERPATH_GLES2:
11137                         RSurf_ActiveModelEntity(ent, true, true, false);
11138                         break;
11139                 case RENDERPATH_GL11:
11140                 case RENDERPATH_GL13:
11141                 case RENDERPATH_GLES1:
11142                         RSurf_ActiveModelEntity(ent, true, false, false);
11143                         break;
11144                 }
11145         }
11146
11147         if (r_transparentdepthmasking.integer)
11148         {
11149                 qboolean setup = false;
11150                 for (i = 0;i < numsurfaces;i = j)
11151                 {
11152                         j = i + 1;
11153                         surface = rsurface.modelsurfaces + surfacelist[i];
11154                         texture = surface->texture;
11155                         rsurface.texture = R_GetCurrentTexture(texture);
11156                         rsurface.lightmaptexture = NULL;
11157                         rsurface.deluxemaptexture = NULL;
11158                         rsurface.uselightmaptexture = false;
11159                         // scan ahead until we find a different texture
11160                         endsurface = min(i + 1024, numsurfaces);
11161                         texturenumsurfaces = 0;
11162                         texturesurfacelist[texturenumsurfaces++] = surface;
11163                         for (;j < endsurface;j++)
11164                         {
11165                                 surface = rsurface.modelsurfaces + surfacelist[j];
11166                                 if (texture != surface->texture)
11167                                         break;
11168                                 texturesurfacelist[texturenumsurfaces++] = surface;
11169                         }
11170                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11171                                 continue;
11172                         // render the range of surfaces as depth
11173                         if (!setup)
11174                         {
11175                                 setup = true;
11176                                 GL_ColorMask(0,0,0,0);
11177                                 GL_Color(1,1,1,1);
11178                                 GL_DepthTest(true);
11179                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11180                                 GL_DepthMask(true);
11181 //                              R_Mesh_ResetTextureState();
11182                         }
11183                         RSurf_SetupDepthAndCulling();
11184                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11185                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11186                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11187                         RSurf_DrawBatch();
11188                 }
11189                 if (setup)
11190                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11191         }
11192
11193         for (i = 0;i < numsurfaces;i = j)
11194         {
11195                 j = i + 1;
11196                 surface = rsurface.modelsurfaces + surfacelist[i];
11197                 texture = surface->texture;
11198                 rsurface.texture = R_GetCurrentTexture(texture);
11199                 // scan ahead until we find a different texture
11200                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11201                 texturenumsurfaces = 0;
11202                 texturesurfacelist[texturenumsurfaces++] = surface;
11203                 if(FAKELIGHT_ENABLED)
11204                 {
11205                         rsurface.lightmaptexture = NULL;
11206                         rsurface.deluxemaptexture = NULL;
11207                         rsurface.uselightmaptexture = false;
11208                         for (;j < endsurface;j++)
11209                         {
11210                                 surface = rsurface.modelsurfaces + surfacelist[j];
11211                                 if (texture != surface->texture)
11212                                         break;
11213                                 texturesurfacelist[texturenumsurfaces++] = surface;
11214                         }
11215                 }
11216                 else
11217                 {
11218                         rsurface.lightmaptexture = surface->lightmaptexture;
11219                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11220                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11221                         for (;j < endsurface;j++)
11222                         {
11223                                 surface = rsurface.modelsurfaces + surfacelist[j];
11224                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11225                                         break;
11226                                 texturesurfacelist[texturenumsurfaces++] = surface;
11227                         }
11228                 }
11229                 // render the range of surfaces
11230                 if (ent == r_refdef.scene.worldentity)
11231                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11232                 else
11233                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11234         }
11235         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11236 }
11237
11238 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11239 {
11240         // transparent surfaces get pushed off into the transparent queue
11241         int surfacelistindex;
11242         const msurface_t *surface;
11243         vec3_t tempcenter, center;
11244         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11245         {
11246                 surface = texturesurfacelist[surfacelistindex];
11247                 if (r_transparent_sortsurfacesbynearest.integer)
11248                 {
11249                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11250                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11251                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11252                 }
11253                 else
11254                 {
11255                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11256                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11257                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11258                 }
11259                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11260                 if (rsurface.entity->transparent_offset) // transparent offset
11261                 {
11262                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11263                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11264                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11265                 }
11266                 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11267         }
11268 }
11269
11270 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11271 {
11272         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11273                 return;
11274         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11275                 return;
11276         RSurf_SetupDepthAndCulling();
11277         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11278         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11279         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11280         RSurf_DrawBatch();
11281 }
11282
11283 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11284 {
11285         CHECKGLERROR
11286         if (depthonly)
11287                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11288         else if (prepass)
11289         {
11290                 if (!rsurface.texture->currentnumlayers)
11291                         return;
11292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11293                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11294                 else
11295                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11296         }
11297         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11298                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11299         else if (!rsurface.texture->currentnumlayers)
11300                 return;
11301         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11302         {
11303                 // in the deferred case, transparent surfaces were queued during prepass
11304                 if (!r_shadow_usingdeferredprepass)
11305                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11306         }
11307         else
11308         {
11309                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11310                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11311         }
11312         CHECKGLERROR
11313 }
11314
11315 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11316 {
11317         int i, j;
11318         texture_t *texture;
11319         R_FrameData_SetMark();
11320         // break the surface list down into batches by texture and use of lightmapping
11321         for (i = 0;i < numsurfaces;i = j)
11322         {
11323                 j = i + 1;
11324                 // texture is the base texture pointer, rsurface.texture is the
11325                 // current frame/skin the texture is directing us to use (for example
11326                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11327                 // use skin 1 instead)
11328                 texture = surfacelist[i]->texture;
11329                 rsurface.texture = R_GetCurrentTexture(texture);
11330                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11331                 {
11332                         // if this texture is not the kind we want, skip ahead to the next one
11333                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11334                                 ;
11335                         continue;
11336                 }
11337                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11338                 {
11339                         rsurface.lightmaptexture = NULL;
11340                         rsurface.deluxemaptexture = NULL;
11341                         rsurface.uselightmaptexture = false;
11342                         // simply scan ahead until we find a different texture or lightmap state
11343                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11344                                 ;
11345                 }
11346                 else
11347                 {
11348                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11349                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11350                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11351                         // simply scan ahead until we find a different texture or lightmap state
11352                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11353                                 ;
11354                 }
11355                 // render the range of surfaces
11356                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11357         }
11358         R_FrameData_ReturnToMark();
11359 }
11360
11361 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11362 {
11363         CHECKGLERROR
11364         if (depthonly)
11365                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11366         else if (prepass)
11367         {
11368                 if (!rsurface.texture->currentnumlayers)
11369                         return;
11370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11371                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11372                 else
11373                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11374         }
11375         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11376                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11377         else if (!rsurface.texture->currentnumlayers)
11378                 return;
11379         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11380         {
11381                 // in the deferred case, transparent surfaces were queued during prepass
11382                 if (!r_shadow_usingdeferredprepass)
11383                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11384         }
11385         else
11386         {
11387                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11388                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11389         }
11390         CHECKGLERROR
11391 }
11392
11393 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11394 {
11395         int i, j;
11396         texture_t *texture;
11397         R_FrameData_SetMark();
11398         // break the surface list down into batches by texture and use of lightmapping
11399         for (i = 0;i < numsurfaces;i = j)
11400         {
11401                 j = i + 1;
11402                 // texture is the base texture pointer, rsurface.texture is the
11403                 // current frame/skin the texture is directing us to use (for example
11404                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11405                 // use skin 1 instead)
11406                 texture = surfacelist[i]->texture;
11407                 rsurface.texture = R_GetCurrentTexture(texture);
11408                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11409                 {
11410                         // if this texture is not the kind we want, skip ahead to the next one
11411                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11412                                 ;
11413                         continue;
11414                 }
11415                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11416                 {
11417                         rsurface.lightmaptexture = NULL;
11418                         rsurface.deluxemaptexture = NULL;
11419                         rsurface.uselightmaptexture = false;
11420                         // simply scan ahead until we find a different texture or lightmap state
11421                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11422                                 ;
11423                 }
11424                 else
11425                 {
11426                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11427                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11428                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11429                         // simply scan ahead until we find a different texture or lightmap state
11430                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11431                                 ;
11432                 }
11433                 // render the range of surfaces
11434                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11435         }
11436         R_FrameData_ReturnToMark();
11437 }
11438
11439 float locboxvertex3f[6*4*3] =
11440 {
11441         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11442         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11443         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11444         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11445         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11446         1,0,0, 0,0,0, 0,1,0, 1,1,0
11447 };
11448
11449 unsigned short locboxelements[6*2*3] =
11450 {
11451          0, 1, 2, 0, 2, 3,
11452          4, 5, 6, 4, 6, 7,
11453          8, 9,10, 8,10,11,
11454         12,13,14, 12,14,15,
11455         16,17,18, 16,18,19,
11456         20,21,22, 20,22,23
11457 };
11458
11459 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11460 {
11461         int i, j;
11462         cl_locnode_t *loc = (cl_locnode_t *)ent;
11463         vec3_t mins, size;
11464         float vertex3f[6*4*3];
11465         CHECKGLERROR
11466         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11467         GL_DepthMask(false);
11468         GL_DepthRange(0, 1);
11469         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11470         GL_DepthTest(true);
11471         GL_CullFace(GL_NONE);
11472         R_EntityMatrix(&identitymatrix);
11473
11474 //      R_Mesh_ResetTextureState();
11475
11476         i = surfacelist[0];
11477         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11478                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11479                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11480                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11481
11482         if (VectorCompare(loc->mins, loc->maxs))
11483         {
11484                 VectorSet(size, 2, 2, 2);
11485                 VectorMA(loc->mins, -0.5f, size, mins);
11486         }
11487         else
11488         {
11489                 VectorCopy(loc->mins, mins);
11490                 VectorSubtract(loc->maxs, loc->mins, size);
11491         }
11492
11493         for (i = 0;i < 6*4*3;)
11494                 for (j = 0;j < 3;j++, i++)
11495                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11496
11497         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11498         R_SetupShader_Generic_NoTexture(false, false);
11499         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11500 }
11501
11502 void R_DrawLocs(void)
11503 {
11504         int index;
11505         cl_locnode_t *loc, *nearestloc;
11506         vec3_t center;
11507         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11508         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11509         {
11510                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11511                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11512         }
11513 }
11514
11515 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11516 {
11517         if (decalsystem->decals)
11518                 Mem_Free(decalsystem->decals);
11519         memset(decalsystem, 0, sizeof(*decalsystem));
11520 }
11521
11522 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)
11523 {
11524         tridecal_t *decal;
11525         tridecal_t *decals;
11526         int i;
11527
11528         // expand or initialize the system
11529         if (decalsystem->maxdecals <= decalsystem->numdecals)
11530         {
11531                 decalsystem_t old = *decalsystem;
11532                 qboolean useshortelements;
11533                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11534                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11535                 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)));
11536                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11537                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11538                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11539                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11540                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11541                 if (decalsystem->numdecals)
11542                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11543                 if (old.decals)
11544                         Mem_Free(old.decals);
11545                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11546                         decalsystem->element3i[i] = i;
11547                 if (useshortelements)
11548                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11549                                 decalsystem->element3s[i] = i;
11550         }
11551
11552         // grab a decal and search for another free slot for the next one
11553         decals = decalsystem->decals;
11554         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11555         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11556                 ;
11557         decalsystem->freedecal = i;
11558         if (decalsystem->numdecals <= i)
11559                 decalsystem->numdecals = i + 1;
11560
11561         // initialize the decal
11562         decal->lived = 0;
11563         decal->triangleindex = triangleindex;
11564         decal->surfaceindex = surfaceindex;
11565         decal->decalsequence = decalsequence;
11566         decal->color4f[0][0] = c0[0];
11567         decal->color4f[0][1] = c0[1];
11568         decal->color4f[0][2] = c0[2];
11569         decal->color4f[0][3] = 1;
11570         decal->color4f[1][0] = c1[0];
11571         decal->color4f[1][1] = c1[1];
11572         decal->color4f[1][2] = c1[2];
11573         decal->color4f[1][3] = 1;
11574         decal->color4f[2][0] = c2[0];
11575         decal->color4f[2][1] = c2[1];
11576         decal->color4f[2][2] = c2[2];
11577         decal->color4f[2][3] = 1;
11578         decal->vertex3f[0][0] = v0[0];
11579         decal->vertex3f[0][1] = v0[1];
11580         decal->vertex3f[0][2] = v0[2];
11581         decal->vertex3f[1][0] = v1[0];
11582         decal->vertex3f[1][1] = v1[1];
11583         decal->vertex3f[1][2] = v1[2];
11584         decal->vertex3f[2][0] = v2[0];
11585         decal->vertex3f[2][1] = v2[1];
11586         decal->vertex3f[2][2] = v2[2];
11587         decal->texcoord2f[0][0] = t0[0];
11588         decal->texcoord2f[0][1] = t0[1];
11589         decal->texcoord2f[1][0] = t1[0];
11590         decal->texcoord2f[1][1] = t1[1];
11591         decal->texcoord2f[2][0] = t2[0];
11592         decal->texcoord2f[2][1] = t2[1];
11593         TriangleNormal(v0, v1, v2, decal->plane);
11594         VectorNormalize(decal->plane);
11595         decal->plane[3] = DotProduct(v0, decal->plane);
11596 }
11597
11598 extern cvar_t cl_decals_bias;
11599 extern cvar_t cl_decals_models;
11600 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11601 // baseparms, parms, temps
11602 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)
11603 {
11604         int cornerindex;
11605         int index;
11606         float v[9][3];
11607         const float *vertex3f;
11608         const float *normal3f;
11609         int numpoints;
11610         float points[2][9][3];
11611         float temp[3];
11612         float tc[9][2];
11613         float f;
11614         float c[9][4];
11615         const int *e;
11616
11617         e = rsurface.modelelement3i + 3*triangleindex;
11618
11619         vertex3f = rsurface.modelvertex3f;
11620         normal3f = rsurface.modelnormal3f;
11621
11622         if (normal3f)
11623         {
11624                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11625                 {
11626                         index = 3*e[cornerindex];
11627                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11628                 }
11629         }
11630         else
11631         {
11632                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11633                 {
11634                         index = 3*e[cornerindex];
11635                         VectorCopy(vertex3f + index, v[cornerindex]);
11636                 }
11637         }
11638
11639         // cull backfaces
11640         //TriangleNormal(v[0], v[1], v[2], normal);
11641         //if (DotProduct(normal, localnormal) < 0.0f)
11642         //      continue;
11643         // clip by each of the box planes formed from the projection matrix
11644         // if anything survives, we emit the decal
11645         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]);
11646         if (numpoints < 3)
11647                 return;
11648         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]);
11649         if (numpoints < 3)
11650                 return;
11651         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]);
11652         if (numpoints < 3)
11653                 return;
11654         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]);
11655         if (numpoints < 3)
11656                 return;
11657         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]);
11658         if (numpoints < 3)
11659                 return;
11660         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]);
11661         if (numpoints < 3)
11662                 return;
11663         // some part of the triangle survived, so we have to accept it...
11664         if (dynamic)
11665         {
11666                 // dynamic always uses the original triangle
11667                 numpoints = 3;
11668                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11669                 {
11670                         index = 3*e[cornerindex];
11671                         VectorCopy(vertex3f + index, v[cornerindex]);
11672                 }
11673         }
11674         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11675         {
11676                 // convert vertex positions to texcoords
11677                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11678                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11679                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11680                 // calculate distance fade from the projection origin
11681                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11682                 f = bound(0.0f, f, 1.0f);
11683                 c[cornerindex][0] = r * f;
11684                 c[cornerindex][1] = g * f;
11685                 c[cornerindex][2] = b * f;
11686                 c[cornerindex][3] = 1.0f;
11687                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11688         }
11689         if (dynamic)
11690                 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);
11691         else
11692                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11693                         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);
11694 }
11695 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)
11696 {
11697         matrix4x4_t projection;
11698         decalsystem_t *decalsystem;
11699         qboolean dynamic;
11700         dp_model_t *model;
11701         const msurface_t *surface;
11702         const msurface_t *surfaces;
11703         const int *surfacelist;
11704         const texture_t *texture;
11705         int numtriangles;
11706         int numsurfacelist;
11707         int surfacelistindex;
11708         int surfaceindex;
11709         int triangleindex;
11710         float localorigin[3];
11711         float localnormal[3];
11712         float localmins[3];
11713         float localmaxs[3];
11714         float localsize;
11715         //float normal[3];
11716         float planes[6][4];
11717         float angles[3];
11718         bih_t *bih;
11719         int bih_triangles_count;
11720         int bih_triangles[256];
11721         int bih_surfaces[256];
11722
11723         decalsystem = &ent->decalsystem;
11724         model = ent->model;
11725         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11726         {
11727                 R_DecalSystem_Reset(&ent->decalsystem);
11728                 return;
11729         }
11730
11731         if (!model->brush.data_leafs && !cl_decals_models.integer)
11732         {
11733                 if (decalsystem->model)
11734                         R_DecalSystem_Reset(decalsystem);
11735                 return;
11736         }
11737
11738         if (decalsystem->model != model)
11739                 R_DecalSystem_Reset(decalsystem);
11740         decalsystem->model = model;
11741
11742         RSurf_ActiveModelEntity(ent, true, false, false);
11743
11744         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11745         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11746         VectorNormalize(localnormal);
11747         localsize = worldsize*rsurface.inversematrixscale;
11748         localmins[0] = localorigin[0] - localsize;
11749         localmins[1] = localorigin[1] - localsize;
11750         localmins[2] = localorigin[2] - localsize;
11751         localmaxs[0] = localorigin[0] + localsize;
11752         localmaxs[1] = localorigin[1] + localsize;
11753         localmaxs[2] = localorigin[2] + localsize;
11754
11755         //VectorCopy(localnormal, planes[4]);
11756         //VectorVectors(planes[4], planes[2], planes[0]);
11757         AnglesFromVectors(angles, localnormal, NULL, false);
11758         AngleVectors(angles, planes[0], planes[2], planes[4]);
11759         VectorNegate(planes[0], planes[1]);
11760         VectorNegate(planes[2], planes[3]);
11761         VectorNegate(planes[4], planes[5]);
11762         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11763         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11764         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11765         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11766         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11767         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11768
11769 #if 1
11770 // works
11771 {
11772         matrix4x4_t forwardprojection;
11773         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11774         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11775 }
11776 #else
11777 // broken
11778 {
11779         float projectionvector[4][3];
11780         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11781         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11782         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11783         projectionvector[0][0] = planes[0][0] * ilocalsize;
11784         projectionvector[0][1] = planes[1][0] * ilocalsize;
11785         projectionvector[0][2] = planes[2][0] * ilocalsize;
11786         projectionvector[1][0] = planes[0][1] * ilocalsize;
11787         projectionvector[1][1] = planes[1][1] * ilocalsize;
11788         projectionvector[1][2] = planes[2][1] * ilocalsize;
11789         projectionvector[2][0] = planes[0][2] * ilocalsize;
11790         projectionvector[2][1] = planes[1][2] * ilocalsize;
11791         projectionvector[2][2] = planes[2][2] * ilocalsize;
11792         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11793         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11794         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11795         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11796 }
11797 #endif
11798
11799         dynamic = model->surfmesh.isanimated;
11800         numsurfacelist = model->nummodelsurfaces;
11801         surfacelist = model->sortedmodelsurfaces;
11802         surfaces = model->data_surfaces;
11803
11804         bih = NULL;
11805         bih_triangles_count = -1;
11806         if(!dynamic)
11807         {
11808                 if(model->render_bih.numleafs)
11809                         bih = &model->render_bih;
11810                 else if(model->collision_bih.numleafs)
11811                         bih = &model->collision_bih;
11812         }
11813         if(bih)
11814                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11815         if(bih_triangles_count == 0)
11816                 return;
11817         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11818                 return;
11819         if(bih_triangles_count > 0)
11820         {
11821                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11822                 {
11823                         surfaceindex = bih_surfaces[triangleindex];
11824                         surface = surfaces + surfaceindex;
11825                         texture = surface->texture;
11826                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11827                                 continue;
11828                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11829                                 continue;
11830                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11831                 }
11832         }
11833         else
11834         {
11835                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11836                 {
11837                         surfaceindex = surfacelist[surfacelistindex];
11838                         surface = surfaces + surfaceindex;
11839                         // check cull box first because it rejects more than any other check
11840                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11841                                 continue;
11842                         // skip transparent surfaces
11843                         texture = surface->texture;
11844                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11845                                 continue;
11846                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11847                                 continue;
11848                         numtriangles = surface->num_triangles;
11849                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11850                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11851                 }
11852         }
11853 }
11854
11855 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11856 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)
11857 {
11858         int renderentityindex;
11859         float worldmins[3];
11860         float worldmaxs[3];
11861         entity_render_t *ent;
11862
11863         if (!cl_decals_newsystem.integer)
11864                 return;
11865
11866         worldmins[0] = worldorigin[0] - worldsize;
11867         worldmins[1] = worldorigin[1] - worldsize;
11868         worldmins[2] = worldorigin[2] - worldsize;
11869         worldmaxs[0] = worldorigin[0] + worldsize;
11870         worldmaxs[1] = worldorigin[1] + worldsize;
11871         worldmaxs[2] = worldorigin[2] + worldsize;
11872
11873         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11874
11875         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11876         {
11877                 ent = r_refdef.scene.entities[renderentityindex];
11878                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11879                         continue;
11880
11881                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11882         }
11883 }
11884
11885 typedef struct r_decalsystem_splatqueue_s
11886 {
11887         vec3_t worldorigin;
11888         vec3_t worldnormal;
11889         float color[4];
11890         float tcrange[4];
11891         float worldsize;
11892         int decalsequence;
11893 }
11894 r_decalsystem_splatqueue_t;
11895
11896 int r_decalsystem_numqueued = 0;
11897 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11898
11899 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)
11900 {
11901         r_decalsystem_splatqueue_t *queue;
11902
11903         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11904                 return;
11905
11906         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11907         VectorCopy(worldorigin, queue->worldorigin);
11908         VectorCopy(worldnormal, queue->worldnormal);
11909         Vector4Set(queue->color, r, g, b, a);
11910         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11911         queue->worldsize = worldsize;
11912         queue->decalsequence = cl.decalsequence++;
11913 }
11914
11915 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11916 {
11917         int i;
11918         r_decalsystem_splatqueue_t *queue;
11919
11920         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11921                 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);
11922         r_decalsystem_numqueued = 0;
11923 }
11924
11925 extern cvar_t cl_decals_max;
11926 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11927 {
11928         int i;
11929         decalsystem_t *decalsystem = &ent->decalsystem;
11930         int numdecals;
11931         int killsequence;
11932         tridecal_t *decal;
11933         float frametime;
11934         float lifetime;
11935
11936         if (!decalsystem->numdecals)
11937                 return;
11938
11939         if (r_showsurfaces.integer)
11940                 return;
11941
11942         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11943         {
11944                 R_DecalSystem_Reset(decalsystem);
11945                 return;
11946         }
11947
11948         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11949         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11950
11951         if (decalsystem->lastupdatetime)
11952                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11953         else
11954                 frametime = 0;
11955         decalsystem->lastupdatetime = r_refdef.scene.time;
11956         numdecals = decalsystem->numdecals;
11957
11958         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11959         {
11960                 if (decal->color4f[0][3])
11961                 {
11962                         decal->lived += frametime;
11963                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11964                         {
11965                                 memset(decal, 0, sizeof(*decal));
11966                                 if (decalsystem->freedecal > i)
11967                                         decalsystem->freedecal = i;
11968                         }
11969                 }
11970         }
11971         decal = decalsystem->decals;
11972         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11973                 numdecals--;
11974
11975         // collapse the array by shuffling the tail decals into the gaps
11976         for (;;)
11977         {
11978                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11979                         decalsystem->freedecal++;
11980                 if (decalsystem->freedecal == numdecals)
11981                         break;
11982                 decal[decalsystem->freedecal] = decal[--numdecals];
11983         }
11984
11985         decalsystem->numdecals = numdecals;
11986
11987         if (numdecals <= 0)
11988         {
11989                 // if there are no decals left, reset decalsystem
11990                 R_DecalSystem_Reset(decalsystem);
11991         }
11992 }
11993
11994 extern skinframe_t *decalskinframe;
11995 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11996 {
11997         int i;
11998         decalsystem_t *decalsystem = &ent->decalsystem;
11999         int numdecals;
12000         tridecal_t *decal;
12001         float faderate;
12002         float alpha;
12003         float *v3f;
12004         float *c4f;
12005         float *t2f;
12006         const int *e;
12007         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12008         int numtris = 0;
12009
12010         numdecals = decalsystem->numdecals;
12011         if (!numdecals)
12012                 return;
12013
12014         if (r_showsurfaces.integer)
12015                 return;
12016
12017         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12018         {
12019                 R_DecalSystem_Reset(decalsystem);
12020                 return;
12021         }
12022
12023         // if the model is static it doesn't matter what value we give for
12024         // wantnormals and wanttangents, so this logic uses only rules applicable
12025         // to a model, knowing that they are meaningless otherwise
12026         if (ent == r_refdef.scene.worldentity)
12027                 RSurf_ActiveWorldEntity();
12028         else
12029                 RSurf_ActiveModelEntity(ent, false, false, false);
12030
12031         decalsystem->lastupdatetime = r_refdef.scene.time;
12032
12033         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12034
12035         // update vertex positions for animated models
12036         v3f = decalsystem->vertex3f;
12037         c4f = decalsystem->color4f;
12038         t2f = decalsystem->texcoord2f;
12039         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12040         {
12041                 if (!decal->color4f[0][3])
12042                         continue;
12043
12044                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12045                         continue;
12046
12047                 // skip backfaces
12048                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12049                         continue;
12050
12051                 // update color values for fading decals
12052                 if (decal->lived >= cl_decals_time.value)
12053                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12054                 else
12055                         alpha = 1.0f;
12056
12057                 c4f[ 0] = decal->color4f[0][0] * alpha;
12058                 c4f[ 1] = decal->color4f[0][1] * alpha;
12059                 c4f[ 2] = decal->color4f[0][2] * alpha;
12060                 c4f[ 3] = 1;
12061                 c4f[ 4] = decal->color4f[1][0] * alpha;
12062                 c4f[ 5] = decal->color4f[1][1] * alpha;
12063                 c4f[ 6] = decal->color4f[1][2] * alpha;
12064                 c4f[ 7] = 1;
12065                 c4f[ 8] = decal->color4f[2][0] * alpha;
12066                 c4f[ 9] = decal->color4f[2][1] * alpha;
12067                 c4f[10] = decal->color4f[2][2] * alpha;
12068                 c4f[11] = 1;
12069
12070                 t2f[0] = decal->texcoord2f[0][0];
12071                 t2f[1] = decal->texcoord2f[0][1];
12072                 t2f[2] = decal->texcoord2f[1][0];
12073                 t2f[3] = decal->texcoord2f[1][1];
12074                 t2f[4] = decal->texcoord2f[2][0];
12075                 t2f[5] = decal->texcoord2f[2][1];
12076
12077                 // update vertex positions for animated models
12078                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12079                 {
12080                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12081                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12082                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12083                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12084                 }
12085                 else
12086                 {
12087                         VectorCopy(decal->vertex3f[0], v3f);
12088                         VectorCopy(decal->vertex3f[1], v3f + 3);
12089                         VectorCopy(decal->vertex3f[2], v3f + 6);
12090                 }
12091
12092                 if (r_refdef.fogenabled)
12093                 {
12094                         alpha = RSurf_FogVertex(v3f);
12095                         VectorScale(c4f, alpha, c4f);
12096                         alpha = RSurf_FogVertex(v3f + 3);
12097                         VectorScale(c4f + 4, alpha, c4f + 4);
12098                         alpha = RSurf_FogVertex(v3f + 6);
12099                         VectorScale(c4f + 8, alpha, c4f + 8);
12100                 }
12101
12102                 v3f += 9;
12103                 c4f += 12;
12104                 t2f += 6;
12105                 numtris++;
12106         }
12107
12108         if (numtris > 0)
12109         {
12110                 r_refdef.stats[r_stat_drawndecals] += numtris;
12111
12112                 // now render the decals all at once
12113                 // (this assumes they all use one particle font texture!)
12114                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
12115 //              R_Mesh_ResetTextureState();
12116                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12117                 GL_DepthMask(false);
12118                 GL_DepthRange(0, 1);
12119                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12120                 GL_DepthTest(true);
12121                 GL_CullFace(GL_NONE);
12122                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12123                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12124                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12125         }
12126 }
12127
12128 static void R_DrawModelDecals(void)
12129 {
12130         int i, numdecals;
12131
12132         // fade faster when there are too many decals
12133         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12134         for (i = 0;i < r_refdef.scene.numentities;i++)
12135                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12136
12137         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12138         for (i = 0;i < r_refdef.scene.numentities;i++)
12139                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12140                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12141
12142         R_DecalSystem_ApplySplatEntitiesQueue();
12143
12144         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12145         for (i = 0;i < r_refdef.scene.numentities;i++)
12146                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12147
12148         r_refdef.stats[r_stat_totaldecals] += numdecals;
12149
12150         if (r_showsurfaces.integer)
12151                 return;
12152
12153         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12154
12155         for (i = 0;i < r_refdef.scene.numentities;i++)
12156         {
12157                 if (!r_refdef.viewcache.entityvisible[i])
12158                         continue;
12159                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12160                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12161         }
12162 }
12163
12164 extern cvar_t mod_collision_bih;
12165 static void R_DrawDebugModel(void)
12166 {
12167         entity_render_t *ent = rsurface.entity;
12168         int i, j, k, l, flagsmask;
12169         const msurface_t *surface;
12170         dp_model_t *model = ent->model;
12171         vec3_t v;
12172
12173         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12174                 return;
12175
12176         if (r_showoverdraw.value > 0)
12177         {
12178                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12179                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12180                 R_SetupShader_Generic_NoTexture(false, false);
12181                 GL_DepthTest(false);
12182                 GL_DepthMask(false);
12183                 GL_DepthRange(0, 1);
12184                 GL_BlendFunc(GL_ONE, GL_ONE);
12185                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12186                 {
12187                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12188                                 continue;
12189                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12190                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12191                         {
12192                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12193                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12194                                 if (!rsurface.texture->currentlayers->depthmask)
12195                                         GL_Color(c, 0, 0, 1.0f);
12196                                 else if (ent == r_refdef.scene.worldentity)
12197                                         GL_Color(c, c, c, 1.0f);
12198                                 else
12199                                         GL_Color(0, c, 0, 1.0f);
12200                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12201                                 RSurf_DrawBatch();
12202                         }
12203                 }
12204                 rsurface.texture = NULL;
12205         }
12206
12207         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12208
12209 //      R_Mesh_ResetTextureState();
12210         R_SetupShader_Generic_NoTexture(false, false);
12211         GL_DepthRange(0, 1);
12212         GL_DepthTest(!r_showdisabledepthtest.integer);
12213         GL_DepthMask(false);
12214         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12215
12216         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12217         {
12218                 int triangleindex;
12219                 int bihleafindex;
12220                 qboolean cullbox = false;
12221                 const q3mbrush_t *brush;
12222                 const bih_t *bih = &model->collision_bih;
12223                 const bih_leaf_t *bihleaf;
12224                 float vertex3f[3][3];
12225                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12226                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12227                 {
12228                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12229                                 continue;
12230                         switch (bihleaf->type)
12231                         {
12232                         case BIH_BRUSH:
12233                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12234                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12235                                 {
12236                                         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);
12237                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12238                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12239                                 }
12240                                 break;
12241                         case BIH_COLLISIONTRIANGLE:
12242                                 triangleindex = bihleaf->itemindex;
12243                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12244                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12245                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12246                                 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);
12247                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12248                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12249                                 break;
12250                         case BIH_RENDERTRIANGLE:
12251                                 triangleindex = bihleaf->itemindex;
12252                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12253                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12254                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12255                                 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);
12256                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12257                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12258                                 break;
12259                         }
12260                 }
12261         }
12262
12263         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12264
12265 #ifndef USE_GLES2
12266         if (r_showtris.integer && qglPolygonMode)
12267         {
12268                 if (r_showdisabledepthtest.integer)
12269                 {
12270                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12271                         GL_DepthMask(false);
12272                 }
12273                 else
12274                 {
12275                         GL_BlendFunc(GL_ONE, GL_ZERO);
12276                         GL_DepthMask(true);
12277                 }
12278                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12279                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12280                 {
12281                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12282                                 continue;
12283                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12284                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12285                         {
12286                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12287                                 if (!rsurface.texture->currentlayers->depthmask)
12288                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12289                                 else if (ent == r_refdef.scene.worldentity)
12290                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12291                                 else
12292                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12293                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12294                                 RSurf_DrawBatch();
12295                         }
12296                 }
12297                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12298                 rsurface.texture = NULL;
12299         }
12300
12301         if (r_shownormals.value != 0 && qglBegin)
12302         {
12303                 if (r_showdisabledepthtest.integer)
12304                 {
12305                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12306                         GL_DepthMask(false);
12307                 }
12308                 else
12309                 {
12310                         GL_BlendFunc(GL_ONE, GL_ZERO);
12311                         GL_DepthMask(true);
12312                 }
12313                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12314                 {
12315                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12316                                 continue;
12317                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12318                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12319                         {
12320                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12321                                 qglBegin(GL_LINES);
12322                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12323                                 {
12324                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12325                                         {
12326                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12327                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12328                                                 qglVertex3f(v[0], v[1], v[2]);
12329                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12330                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12331                                                 qglVertex3f(v[0], v[1], v[2]);
12332                                         }
12333                                 }
12334                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12335                                 {
12336                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12337                                         {
12338                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12339                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12340                                                 qglVertex3f(v[0], v[1], v[2]);
12341                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12342                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12343                                                 qglVertex3f(v[0], v[1], v[2]);
12344                                         }
12345                                 }
12346                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12347                                 {
12348                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12349                                         {
12350                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12351                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12352                                                 qglVertex3f(v[0], v[1], v[2]);
12353                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12354                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12355                                                 qglVertex3f(v[0], v[1], v[2]);
12356                                         }
12357                                 }
12358                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12359                                 {
12360                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12361                                         {
12362                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12363                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12364                                                 qglVertex3f(v[0], v[1], v[2]);
12365                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12366                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12367                                                 qglVertex3f(v[0], v[1], v[2]);
12368                                         }
12369                                 }
12370                                 qglEnd();
12371                                 CHECKGLERROR
12372                         }
12373                 }
12374                 rsurface.texture = NULL;
12375         }
12376 #endif
12377 }
12378
12379 int r_maxsurfacelist = 0;
12380 const msurface_t **r_surfacelist = NULL;
12381 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12382 {
12383         int i, j, endj, flagsmask;
12384         dp_model_t *model = r_refdef.scene.worldmodel;
12385         msurface_t *surfaces;
12386         unsigned char *update;
12387         int numsurfacelist = 0;
12388         if (model == NULL)
12389                 return;
12390
12391         if (r_maxsurfacelist < model->num_surfaces)
12392         {
12393                 r_maxsurfacelist = model->num_surfaces;
12394                 if (r_surfacelist)
12395                         Mem_Free((msurface_t**)r_surfacelist);
12396                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12397         }
12398
12399         RSurf_ActiveWorldEntity();
12400
12401         surfaces = model->data_surfaces;
12402         update = model->brushq1.lightmapupdateflags;
12403
12404         // update light styles on this submodel
12405         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12406         {
12407                 model_brush_lightstyleinfo_t *style;
12408                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12409                 {
12410                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12411                         {
12412                                 int *list = style->surfacelist;
12413                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12414                                 for (j = 0;j < style->numsurfaces;j++)
12415                                         update[list[j]] = true;
12416                         }
12417                 }
12418         }
12419
12420         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12421
12422         if (debug)
12423         {
12424                 R_DrawDebugModel();
12425                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12426                 return;
12427         }
12428
12429         rsurface.lightmaptexture = NULL;
12430         rsurface.deluxemaptexture = NULL;
12431         rsurface.uselightmaptexture = false;
12432         rsurface.texture = NULL;
12433         rsurface.rtlight = NULL;
12434         numsurfacelist = 0;
12435         // add visible surfaces to draw list
12436         for (i = 0;i < model->nummodelsurfaces;i++)
12437         {
12438                 j = model->sortedmodelsurfaces[i];
12439                 if (r_refdef.viewcache.world_surfacevisible[j])
12440                         r_surfacelist[numsurfacelist++] = surfaces + j;
12441         }
12442         // update lightmaps if needed
12443         if (model->brushq1.firstrender)
12444         {
12445                 model->brushq1.firstrender = false;
12446                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12447                         if (update[j])
12448                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12449         }
12450         else if (update)
12451         {
12452                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12453                         if (r_refdef.viewcache.world_surfacevisible[j])
12454                                 if (update[j])
12455                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12456         }
12457         // don't do anything if there were no surfaces
12458         if (!numsurfacelist)
12459         {
12460                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12461                 return;
12462         }
12463         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12464
12465         // add to stats if desired
12466         if (r_speeds.integer && !skysurfaces && !depthonly)
12467         {
12468                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12469                 for (j = 0;j < numsurfacelist;j++)
12470                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12471         }
12472
12473         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12474 }
12475
12476 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12477 {
12478         int i, j, endj, flagsmask;
12479         dp_model_t *model = ent->model;
12480         msurface_t *surfaces;
12481         unsigned char *update;
12482         int numsurfacelist = 0;
12483         if (model == NULL)
12484                 return;
12485
12486         if (r_maxsurfacelist < model->num_surfaces)
12487         {
12488                 r_maxsurfacelist = model->num_surfaces;
12489                 if (r_surfacelist)
12490                         Mem_Free((msurface_t **)r_surfacelist);
12491                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12492         }
12493
12494         // if the model is static it doesn't matter what value we give for
12495         // wantnormals and wanttangents, so this logic uses only rules applicable
12496         // to a model, knowing that they are meaningless otherwise
12497         if (ent == r_refdef.scene.worldentity)
12498                 RSurf_ActiveWorldEntity();
12499         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12500                 RSurf_ActiveModelEntity(ent, false, false, false);
12501         else if (prepass)
12502                 RSurf_ActiveModelEntity(ent, true, true, true);
12503         else if (depthonly)
12504         {
12505                 switch (vid.renderpath)
12506                 {
12507                 case RENDERPATH_GL20:
12508                 case RENDERPATH_D3D9:
12509                 case RENDERPATH_D3D10:
12510                 case RENDERPATH_D3D11:
12511                 case RENDERPATH_SOFT:
12512                 case RENDERPATH_GLES2:
12513                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12514                         break;
12515                 case RENDERPATH_GL11:
12516                 case RENDERPATH_GL13:
12517                 case RENDERPATH_GLES1:
12518                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12519                         break;
12520                 }
12521         }
12522         else
12523         {
12524                 switch (vid.renderpath)
12525                 {
12526                 case RENDERPATH_GL20:
12527                 case RENDERPATH_D3D9:
12528                 case RENDERPATH_D3D10:
12529                 case RENDERPATH_D3D11:
12530                 case RENDERPATH_SOFT:
12531                 case RENDERPATH_GLES2:
12532                         RSurf_ActiveModelEntity(ent, true, true, false);
12533                         break;
12534                 case RENDERPATH_GL11:
12535                 case RENDERPATH_GL13:
12536                 case RENDERPATH_GLES1:
12537                         RSurf_ActiveModelEntity(ent, true, false, false);
12538                         break;
12539                 }
12540         }
12541
12542         surfaces = model->data_surfaces;
12543         update = model->brushq1.lightmapupdateflags;
12544
12545         // update light styles
12546         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12547         {
12548                 model_brush_lightstyleinfo_t *style;
12549                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12550                 {
12551                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12552                         {
12553                                 int *list = style->surfacelist;
12554                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12555                                 for (j = 0;j < style->numsurfaces;j++)
12556                                         update[list[j]] = true;
12557                         }
12558                 }
12559         }
12560
12561         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12562
12563         if (debug)
12564         {
12565                 R_DrawDebugModel();
12566                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12567                 return;
12568         }
12569
12570         rsurface.lightmaptexture = NULL;
12571         rsurface.deluxemaptexture = NULL;
12572         rsurface.uselightmaptexture = false;
12573         rsurface.texture = NULL;
12574         rsurface.rtlight = NULL;
12575         numsurfacelist = 0;
12576         // add visible surfaces to draw list
12577         for (i = 0;i < model->nummodelsurfaces;i++)
12578                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12579         // don't do anything if there were no surfaces
12580         if (!numsurfacelist)
12581         {
12582                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12583                 return;
12584         }
12585         // update lightmaps if needed
12586         if (update)
12587         {
12588                 int updated = 0;
12589                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12590                 {
12591                         if (update[j])
12592                         {
12593                                 updated++;
12594                                 R_BuildLightMap(ent, surfaces + j);
12595                         }
12596                 }
12597         }
12598
12599         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12600
12601         // add to stats if desired
12602         if (r_speeds.integer && !skysurfaces && !depthonly)
12603         {
12604                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12605                 for (j = 0;j < numsurfacelist;j++)
12606                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12607         }
12608
12609         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12610 }
12611
12612 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12613 {
12614         static texture_t texture;
12615         static msurface_t surface;
12616         const msurface_t *surfacelist = &surface;
12617
12618         // fake enough texture and surface state to render this geometry
12619
12620         texture.update_lastrenderframe = -1; // regenerate this texture
12621         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12622         texture.currentskinframe = skinframe;
12623         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12624         texture.offsetmapping = OFFSETMAPPING_OFF;
12625         texture.offsetscale = 1;
12626         texture.specularscalemod = 1;
12627         texture.specularpowermod = 1;
12628         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12629         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12630         // JUST GREP FOR "specularscalemod = 1".
12631
12632         surface.texture = &texture;
12633         surface.num_triangles = numtriangles;
12634         surface.num_firsttriangle = firsttriangle;
12635         surface.num_vertices = numvertices;
12636         surface.num_firstvertex = firstvertex;
12637
12638         // now render it
12639         rsurface.texture = R_GetCurrentTexture(surface.texture);
12640         rsurface.lightmaptexture = NULL;
12641         rsurface.deluxemaptexture = NULL;
12642         rsurface.uselightmaptexture = false;
12643         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12644 }
12645
12646 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)
12647 {
12648         static msurface_t surface;
12649         const msurface_t *surfacelist = &surface;
12650
12651         // fake enough texture and surface state to render this geometry
12652         surface.texture = texture;
12653         surface.num_triangles = numtriangles;
12654         surface.num_firsttriangle = firsttriangle;
12655         surface.num_vertices = numvertices;
12656         surface.num_firstvertex = firstvertex;
12657
12658         // now render it
12659         rsurface.texture = R_GetCurrentTexture(surface.texture);
12660         rsurface.lightmaptexture = NULL;
12661         rsurface.deluxemaptexture = NULL;
12662         rsurface.uselightmaptexture = false;
12663         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12664 }