]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
29021091cce4dc138c1d734a14b4be637892130f
[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 "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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 (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 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) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
83
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
97 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)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 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"};
101 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"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 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"};
104 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"};
105 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"};
106 cvar_t r_showspriteedges = {0, "r_showspriteedges", "0", "renders a debug outline to show the polygon shape of each sprite frame rendered (may be 2 or more in case of interpolated animations), for debugging rendering bugs with specific view types"};
107 cvar_t r_showparticleedges = {0, "r_showparticleedges", "0", "renders a debug outline to show the polygon shape of each particle, for debugging rendering bugs with specific view types"};
108 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
109 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
110 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
111 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
112 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
113 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
114 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
115 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
116 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)"};
117 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)"};
118 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
119 cvar_t r_cullentities_trace_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
120 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
121 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
122 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
123 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
124 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
125 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
126
127 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
128 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
129 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
130
131 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
132 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
133 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
134 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
135 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
136
137 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
138 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
139 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
140 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."};
141 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
142 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
143 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
144 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."};
145 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
146 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
147 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
148 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."};
149 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
150 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"};
151 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"};
152 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
153 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
154 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
155 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
156 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
157 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"};
158 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
159 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
160 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
161 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
162 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
163
164 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
165 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
166 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
167 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
168 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
169 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
170 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
171 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
172
173 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)"};
174 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"};
175
176 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
177 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
178 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
179
180 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"};
181 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"};
182 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
183 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"};
184 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
185 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
186 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"};
187 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)"};
188 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)"};
189 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
190
191 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
192 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)"};
193 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
194 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)"};
195 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
196 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)"};
197 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)"};
198 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
199 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"};
200 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."};
201 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206 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)"};
207 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)"};
208 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)"};
209 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)"};
210
211 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)"};
212 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
213 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
214 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"};
215 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
216 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
217 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
218 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"};
219 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"};
220
221 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
222 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
223 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
224 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
225
226 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
227 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
228
229 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
230 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
231 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
232 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
233 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
234 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
235
236 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
237 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
238 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
239 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
240 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
241 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
242 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
243 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
244 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
245 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
246
247 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"};
248
249 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"};
250
251 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
252
253 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
254
255 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)"};
256 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)"};
257 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
258 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
259
260 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
261 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"};
262
263 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."};
264
265 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)"};
266 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
267 {
268         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
269         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
270         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
271         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
272 };
273
274 extern cvar_t v_glslgamma_2d;
275
276 extern qboolean v_flipped_state;
277
278 r_framebufferstate_t r_fb;
279
280 /// shadow volume bsp struct with automatically growing nodes buffer
281 svbsp_t r_svbsp;
282
283 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
284
285 rtexture_t *r_texture_blanknormalmap;
286 rtexture_t *r_texture_white;
287 rtexture_t *r_texture_grey128;
288 rtexture_t *r_texture_black;
289 rtexture_t *r_texture_notexture;
290 rtexture_t *r_texture_whitecube;
291 rtexture_t *r_texture_normalizationcube;
292 rtexture_t *r_texture_fogattenuation;
293 rtexture_t *r_texture_fogheighttexture;
294 rtexture_t *r_texture_gammaramps;
295 unsigned int r_texture_gammaramps_serial;
296 //rtexture_t *r_texture_fogintensity;
297 rtexture_t *r_texture_reflectcube;
298
299 // TODO: hash lookups?
300 typedef struct cubemapinfo_s
301 {
302         char basename[64];
303         rtexture_t *texture;
304 }
305 cubemapinfo_t;
306
307 int r_texture_numcubemaps;
308 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
309
310 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
311 unsigned int r_numqueries;
312 unsigned int r_maxqueries;
313
314 typedef struct r_qwskincache_s
315 {
316         char name[MAX_QPATH];
317         skinframe_t *skinframe;
318 }
319 r_qwskincache_t;
320
321 static r_qwskincache_t *r_qwskincache;
322 static int r_qwskincache_size;
323
324 /// vertex coordinates for a quad that covers the screen exactly
325 extern const float r_screenvertex3f[12];
326 const float r_screenvertex3f[12] =
327 {
328         0, 0, 0,
329         1, 0, 0,
330         1, 1, 0,
331         0, 1, 0
332 };
333
334 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = in[0] * r;
340                 out[1] = in[1] * g;
341                 out[2] = in[2] * b;
342                 out[3] = in[3];
343                 in += 4;
344                 out += 4;
345         }
346 }
347
348 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
349 {
350         int i;
351         for (i = 0;i < verts;i++)
352         {
353                 out[0] = r;
354                 out[1] = g;
355                 out[2] = b;
356                 out[3] = a;
357                 out += 4;
358         }
359 }
360
361 // FIXME: move this to client?
362 void FOG_clear(void)
363 {
364         if (gamemode == GAME_NEHAHRA)
365         {
366                 Cvar_Set("gl_fogenable", "0");
367                 Cvar_Set("gl_fogdensity", "0.2");
368                 Cvar_Set("gl_fogred", "0.3");
369                 Cvar_Set("gl_foggreen", "0.3");
370                 Cvar_Set("gl_fogblue", "0.3");
371         }
372         r_refdef.fog_density = 0;
373         r_refdef.fog_red = 0;
374         r_refdef.fog_green = 0;
375         r_refdef.fog_blue = 0;
376         r_refdef.fog_alpha = 1;
377         r_refdef.fog_start = 0;
378         r_refdef.fog_end = 16384;
379         r_refdef.fog_height = 1<<30;
380         r_refdef.fog_fadedepth = 128;
381         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
382 }
383
384 static void R_BuildBlankTextures(void)
385 {
386         unsigned char data[4];
387         data[2] = 128; // normal X
388         data[1] = 128; // normal Y
389         data[0] = 255; // normal Z
390         data[3] = 255; // height
391         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392         data[0] = 255;
393         data[1] = 255;
394         data[2] = 255;
395         data[3] = 255;
396         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 128;
398         data[1] = 128;
399         data[2] = 128;
400         data[3] = 255;
401         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 0;
403         data[1] = 0;
404         data[2] = 0;
405         data[3] = 255;
406         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNoTexture(void)
410 {
411         int x, y;
412         unsigned char pix[16][16][4];
413         // this makes a light grey/dark grey checkerboard texture
414         for (y = 0;y < 16;y++)
415         {
416                 for (x = 0;x < 16;x++)
417                 {
418                         if ((y < 8) ^ (x < 8))
419                         {
420                                 pix[y][x][0] = 128;
421                                 pix[y][x][1] = 128;
422                                 pix[y][x][2] = 128;
423                                 pix[y][x][3] = 255;
424                         }
425                         else
426                         {
427                                 pix[y][x][0] = 64;
428                                 pix[y][x][1] = 64;
429                                 pix[y][x][2] = 64;
430                                 pix[y][x][3] = 255;
431                         }
432                 }
433         }
434         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
435 }
436
437 static void R_BuildWhiteCube(void)
438 {
439         unsigned char data[6*1*1*4];
440         memset(data, 255, sizeof(data));
441         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
442 }
443
444 static void R_BuildNormalizationCube(void)
445 {
446         int x, y, side;
447         vec3_t v;
448         vec_t s, t, intensity;
449 #define NORMSIZE 64
450         unsigned char *data;
451         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
452         for (side = 0;side < 6;side++)
453         {
454                 for (y = 0;y < NORMSIZE;y++)
455                 {
456                         for (x = 0;x < NORMSIZE;x++)
457                         {
458                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
460                                 switch(side)
461                                 {
462                                 default:
463                                 case 0:
464                                         v[0] = 1;
465                                         v[1] = -t;
466                                         v[2] = -s;
467                                         break;
468                                 case 1:
469                                         v[0] = -1;
470                                         v[1] = -t;
471                                         v[2] = s;
472                                         break;
473                                 case 2:
474                                         v[0] = s;
475                                         v[1] = 1;
476                                         v[2] = t;
477                                         break;
478                                 case 3:
479                                         v[0] = s;
480                                         v[1] = -1;
481                                         v[2] = -t;
482                                         break;
483                                 case 4:
484                                         v[0] = s;
485                                         v[1] = -t;
486                                         v[2] = 1;
487                                         break;
488                                 case 5:
489                                         v[0] = -s;
490                                         v[1] = -t;
491                                         v[2] = -1;
492                                         break;
493                                 }
494                                 intensity = 127.0f / sqrt(DotProduct(v, v));
495                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
496                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
497                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
498                                 data[((side*64+y)*64+x)*4+3] = 255;
499                         }
500                 }
501         }
502         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
503         Mem_Free(data);
504 }
505
506 static void R_BuildFogTexture(void)
507 {
508         int x, b;
509 #define FOGWIDTH 256
510         unsigned char data1[FOGWIDTH][4];
511         //unsigned char data2[FOGWIDTH][4];
512         double d, r, alpha;
513
514         r_refdef.fogmasktable_start = r_refdef.fog_start;
515         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
516         r_refdef.fogmasktable_range = r_refdef.fogrange;
517         r_refdef.fogmasktable_density = r_refdef.fog_density;
518
519         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
520         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
521         {
522                 d = (x * r - r_refdef.fogmasktable_start);
523                 if(developer_extra.integer)
524                         Con_DPrintf("%f ", d);
525                 d = max(0, d);
526                 if (r_fog_exp2.integer)
527                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
528                 else
529                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
530                 if(developer_extra.integer)
531                         Con_DPrintf(" : %f ", alpha);
532                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
533                 if(developer_extra.integer)
534                         Con_DPrintf(" = %f\n", alpha);
535                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
536         }
537
538         for (x = 0;x < FOGWIDTH;x++)
539         {
540                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541                 data1[x][0] = b;
542                 data1[x][1] = b;
543                 data1[x][2] = b;
544                 data1[x][3] = 255;
545                 //data2[x][0] = 255 - b;
546                 //data2[x][1] = 255 - b;
547                 //data2[x][2] = 255 - b;
548                 //data2[x][3] = 255;
549         }
550         if (r_texture_fogattenuation)
551         {
552                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
554         }
555         else
556         {
557                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
558                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
559         }
560 }
561
562 static void R_BuildFogHeightTexture(void)
563 {
564         unsigned char *inpixels;
565         int size;
566         int x;
567         int y;
568         int j;
569         float c[4];
570         float f;
571         inpixels = NULL;
572         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
573         if (r_refdef.fogheighttexturename[0])
574                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
575         if (!inpixels)
576         {
577                 r_refdef.fog_height_tablesize = 0;
578                 if (r_texture_fogheighttexture)
579                         R_FreeTexture(r_texture_fogheighttexture);
580                 r_texture_fogheighttexture = NULL;
581                 if (r_refdef.fog_height_table2d)
582                         Mem_Free(r_refdef.fog_height_table2d);
583                 r_refdef.fog_height_table2d = NULL;
584                 if (r_refdef.fog_height_table1d)
585                         Mem_Free(r_refdef.fog_height_table1d);
586                 r_refdef.fog_height_table1d = NULL;
587                 return;
588         }
589         size = image_width;
590         r_refdef.fog_height_tablesize = size;
591         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
592         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
593         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
594         Mem_Free(inpixels);
595         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
596         // average fog color table accounting for every fog layer between a point
597         // and the camera.  (Note: attenuation is handled separately!)
598         for (y = 0;y < size;y++)
599         {
600                 for (x = 0;x < size;x++)
601                 {
602                         Vector4Clear(c);
603                         f = 0;
604                         if (x < y)
605                         {
606                                 for (j = x;j <= y;j++)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         else
613                         {
614                                 for (j = x;j >= y;j--)
615                                 {
616                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617                                         f++;
618                                 }
619                         }
620                         f = 1.0f / f;
621                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
622                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
623                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
624                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
625                 }
626         }
627         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
628 }
629
630 //=======================================================================================================================================================
631
632 static const char *builtinshaderstrings[] =
633 {
634 #include "shader_glsl.h"
635 0
636 };
637
638 const char *builtinhlslshaderstrings[] =
639 {
640 #include "shader_hlsl.h"
641 0
642 };
643
644 //=======================================================================================================================================================
645
646 typedef struct shaderpermutationinfo_s
647 {
648         const char *pretext;
649         const char *name;
650 }
651 shaderpermutationinfo_t;
652
653 typedef struct shadermodeinfo_s
654 {
655         const char *sourcebasename;
656         const char *extension;
657         const char **builtinshaderstrings;
658         const char *pretext;
659         const char *name;
660         char *filename;
661         char *builtinstring;
662         int builtincrc;
663 }
664 shadermodeinfo_t;
665
666 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
667 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
668 {
669         {"#define USEDIFFUSE\n", " diffuse"},
670         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
671         {"#define USEVIEWTINT\n", " viewtint"},
672         {"#define USECOLORMAPPING\n", " colormapping"},
673         {"#define USESATURATION\n", " saturation"},
674         {"#define USEFOGINSIDE\n", " foginside"},
675         {"#define USEFOGOUTSIDE\n", " fogoutside"},
676         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
677         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
678         {"#define USEGAMMARAMPS\n", " gammaramps"},
679         {"#define USECUBEFILTER\n", " cubefilter"},
680         {"#define USEGLOW\n", " glow"},
681         {"#define USEBLOOM\n", " bloom"},
682         {"#define USESPECULAR\n", " specular"},
683         {"#define USEPOSTPROCESSING\n", " postprocessing"},
684         {"#define USEREFLECTION\n", " reflection"},
685         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
686         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
687         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
688         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
689         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
690         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
691         {"#define USEALPHAKILL\n", " alphakill"},
692         {"#define USEREFLECTCUBE\n", " reflectcube"},
693         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
694         {"#define USEBOUNCEGRID\n", " bouncegrid"},
695         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
696         {"#define USETRIPPY\n", " trippy"},
697         {"#define USEDEPTHRGB\n", " depthrgb"},
698         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
699         {"#define USESKELETAL\n", " skeletal"},
700         {"#define USEOCCLUDE\n", " occlude"}
701 };
702
703 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
704 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
705 {
706         // SHADERLANGUAGE_GLSL
707         {
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725         },
726         // SHADERLANGUAGE_HLSL
727         {
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
745         },
746 };
747
748 struct r_glsl_permutation_s;
749 typedef struct r_glsl_permutation_s
750 {
751         /// hash lookup data
752         struct r_glsl_permutation_s *hashnext;
753         unsigned int mode;
754         dpuint64 permutation;
755
756         /// indicates if we have tried compiling this permutation already
757         qboolean compiled;
758         /// 0 if compilation failed
759         int program;
760         // texture units assigned to each detected uniform
761         int tex_Texture_First;
762         int tex_Texture_Second;
763         int tex_Texture_GammaRamps;
764         int tex_Texture_Normal;
765         int tex_Texture_Color;
766         int tex_Texture_Gloss;
767         int tex_Texture_Glow;
768         int tex_Texture_SecondaryNormal;
769         int tex_Texture_SecondaryColor;
770         int tex_Texture_SecondaryGloss;
771         int tex_Texture_SecondaryGlow;
772         int tex_Texture_Pants;
773         int tex_Texture_Shirt;
774         int tex_Texture_FogHeightTexture;
775         int tex_Texture_FogMask;
776         int tex_Texture_Lightmap;
777         int tex_Texture_Deluxemap;
778         int tex_Texture_Attenuation;
779         int tex_Texture_Cube;
780         int tex_Texture_Refraction;
781         int tex_Texture_Reflection;
782         int tex_Texture_ShadowMap2D;
783         int tex_Texture_CubeProjection;
784         int tex_Texture_ScreenNormalMap;
785         int tex_Texture_ScreenDiffuse;
786         int tex_Texture_ScreenSpecular;
787         int tex_Texture_ReflectMask;
788         int tex_Texture_ReflectCube;
789         int tex_Texture_BounceGrid;
790         /// locations of detected uniforms in program object, or -1 if not found
791         int loc_Texture_First;
792         int loc_Texture_Second;
793         int loc_Texture_GammaRamps;
794         int loc_Texture_Normal;
795         int loc_Texture_Color;
796         int loc_Texture_Gloss;
797         int loc_Texture_Glow;
798         int loc_Texture_SecondaryNormal;
799         int loc_Texture_SecondaryColor;
800         int loc_Texture_SecondaryGloss;
801         int loc_Texture_SecondaryGlow;
802         int loc_Texture_Pants;
803         int loc_Texture_Shirt;
804         int loc_Texture_FogHeightTexture;
805         int loc_Texture_FogMask;
806         int loc_Texture_Lightmap;
807         int loc_Texture_Deluxemap;
808         int loc_Texture_Attenuation;
809         int loc_Texture_Cube;
810         int loc_Texture_Refraction;
811         int loc_Texture_Reflection;
812         int loc_Texture_ShadowMap2D;
813         int loc_Texture_CubeProjection;
814         int loc_Texture_ScreenNormalMap;
815         int loc_Texture_ScreenDiffuse;
816         int loc_Texture_ScreenSpecular;
817         int loc_Texture_ReflectMask;
818         int loc_Texture_ReflectCube;
819         int loc_Texture_BounceGrid;
820         int loc_Alpha;
821         int loc_BloomBlur_Parameters;
822         int loc_ClientTime;
823         int loc_Color_Ambient;
824         int loc_Color_Diffuse;
825         int loc_Color_Specular;
826         int loc_Color_Glow;
827         int loc_Color_Pants;
828         int loc_Color_Shirt;
829         int loc_DeferredColor_Ambient;
830         int loc_DeferredColor_Diffuse;
831         int loc_DeferredColor_Specular;
832         int loc_DeferredMod_Diffuse;
833         int loc_DeferredMod_Specular;
834         int loc_DistortScaleRefractReflect;
835         int loc_EyePosition;
836         int loc_FogColor;
837         int loc_FogHeightFade;
838         int loc_FogPlane;
839         int loc_FogPlaneViewDist;
840         int loc_FogRangeRecip;
841         int loc_LightColor;
842         int loc_LightDir;
843         int loc_LightPosition;
844         int loc_OffsetMapping_ScaleSteps;
845         int loc_OffsetMapping_LodDistance;
846         int loc_OffsetMapping_Bias;
847         int loc_PixelSize;
848         int loc_ReflectColor;
849         int loc_ReflectFactor;
850         int loc_ReflectOffset;
851         int loc_RefractColor;
852         int loc_Saturation;
853         int loc_ScreenCenterRefractReflect;
854         int loc_ScreenScaleRefractReflect;
855         int loc_ScreenToDepth;
856         int loc_ShadowMap_Parameters;
857         int loc_ShadowMap_TextureScale;
858         int loc_SpecularPower;
859         int loc_Skeletal_Transform12;
860         int loc_UserVec1;
861         int loc_UserVec2;
862         int loc_UserVec3;
863         int loc_UserVec4;
864         int loc_ViewTintColor;
865         int loc_ViewToLight;
866         int loc_ModelToLight;
867         int loc_TexMatrix;
868         int loc_BackgroundTexMatrix;
869         int loc_ModelViewProjectionMatrix;
870         int loc_ModelViewMatrix;
871         int loc_PixelToScreenTexCoord;
872         int loc_ModelToReflectCube;
873         int loc_ShadowMapMatrix;
874         int loc_BloomColorSubtract;
875         int loc_NormalmapScrollBlend;
876         int loc_BounceGridMatrix;
877         int loc_BounceGridIntensity;
878         /// uniform block bindings
879         int ubibind_Skeletal_Transform12_UniformBlock;
880         /// uniform block indices
881         int ubiloc_Skeletal_Transform12_UniformBlock;
882 }
883 r_glsl_permutation_t;
884
885 #define SHADERPERMUTATION_HASHSIZE 256
886
887
888 // non-degradable "lightweight" shader parameters to keep the permutations simpler
889 // these can NOT degrade! only use for simple stuff
890 enum
891 {
892         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
893         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
894         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
895         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
896         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
897         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
898         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
899         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
900         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
901         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
902         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
903         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
904         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
905         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
906 };
907 #define SHADERSTATICPARMS_COUNT 14
908
909 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
910 static int shaderstaticparms_count = 0;
911
912 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
913 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
914
915 extern qboolean r_shadow_shadowmapsampler;
916 extern int r_shadow_shadowmappcf;
917 qboolean R_CompileShader_CheckStaticParms(void)
918 {
919         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
920         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
921         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
922
923         // detect all
924         if (r_glsl_saturation_redcompensate.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
926         if (r_glsl_vertextextureblend_usebothalphas.integer)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
928         if (r_shadow_glossexact.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
930         if (r_glsl_postprocess.integer)
931         {
932                 if (r_glsl_postprocess_uservec1_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
934                 if (r_glsl_postprocess_uservec2_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
936                 if (r_glsl_postprocess_uservec3_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
938                 if (r_glsl_postprocess_uservec4_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
940         }
941         if (r_fxaa.integer)
942                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
943         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
944                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
945
946         if (r_shadow_shadowmapsampler)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
948         if (r_shadow_shadowmappcf > 1)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
950         else if (r_shadow_shadowmappcf)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
952         if (r_celshading.integer)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
954         if (r_celoutlines.integer)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
956
957         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
958 }
959
960 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
961         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
962                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
963         else \
964                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
965 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
966 {
967         shaderstaticparms_count = 0;
968
969         // emit all
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
984 }
985
986 /// information about each possible shader permutation
987 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
988 /// currently selected permutation
989 r_glsl_permutation_t *r_glsl_permutation;
990 /// storage for permutations linked in the hash table
991 memexpandablearray_t r_glsl_permutationarray;
992
993 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
994 {
995         //unsigned int hashdepth = 0;
996         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
997         r_glsl_permutation_t *p;
998         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
999         {
1000                 if (p->mode == mode && p->permutation == permutation)
1001                 {
1002                         //if (hashdepth > 10)
1003                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1004                         return p;
1005                 }
1006                 //hashdepth++;
1007         }
1008         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1009         p->mode = mode;
1010         p->permutation = permutation;
1011         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1012         r_glsl_permutationhash[mode][hashindex] = p;
1013         //if (hashdepth > 10)
1014         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1015         return p;
1016 }
1017
1018 static char *R_ShaderStrCat(const char **strings)
1019 {
1020         char *string, *s;
1021         const char **p = strings;
1022         const char *t;
1023         size_t len = 0;
1024         for (p = strings;(t = *p);p++)
1025                 len += strlen(t);
1026         len++;
1027         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1028         len = 0;
1029         for (p = strings;(t = *p);p++)
1030         {
1031                 len = strlen(t);
1032                 memcpy(s, t, len);
1033                 s += len;
1034         }
1035         *s = 0;
1036         return string;
1037 }
1038
1039 static char *R_ShaderStrCat(const char **strings);
1040 static void R_InitShaderModeInfo(void)
1041 {
1042         int i, language;
1043         shadermodeinfo_t *modeinfo;
1044         // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1045         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1046         {
1047                 for (i = 0; i < SHADERMODE_COUNT; i++)
1048                 {
1049                         char filename[MAX_QPATH];
1050                         modeinfo = &shadermodeinfo[language][i];
1051                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1052                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1053                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1054                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1055                 }
1056         }
1057 }
1058
1059 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1060 {
1061         char *shaderstring;
1062         // if the mode has no filename we have to return the builtin string
1063         if (builtinonly || !modeinfo->filename)
1064                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1065         // note that FS_LoadFile appends a 0 byte to make it a valid string
1066         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1067         if (shaderstring)
1068         {
1069                 if (printfromdisknotice)
1070                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1071                 return shaderstring;
1072         }
1073         // fall back to builtinstring
1074         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1075 }
1076
1077 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1078 {
1079         int i;
1080         int ubibind;
1081         int sampler;
1082         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1083         char *sourcestring;
1084         char permutationname[256];
1085         int vertstrings_count = 0;
1086         int geomstrings_count = 0;
1087         int fragstrings_count = 0;
1088         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091
1092         if (p->compiled)
1093                 return;
1094         p->compiled = true;
1095         p->program = 0;
1096
1097         permutationname[0] = 0;
1098         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1099
1100         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1101
1102         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1103         if(vid.support.glshaderversion >= 140)
1104         {
1105                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1106                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1107                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1108                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1109                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1110                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1111         }
1112         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1113         else if(vid.support.glshaderversion >= 130)
1114         {
1115                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1116                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1117                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1118                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1119                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1120                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1121         }
1122         // if we can do #version 120, we should (this adds the invariant keyword)
1123         else if(vid.support.glshaderversion >= 120)
1124         {
1125                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1126                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1127                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1128                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1129                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1130                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1131         }
1132         // GLES also adds several things from GLSL120
1133         switch(vid.renderpath)
1134         {
1135         case RENDERPATH_GLES2:
1136                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1137                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1138                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1139                 break;
1140         default:
1141                 break;
1142         }
1143
1144         // the first pretext is which type of shader to compile as
1145         // (later these will all be bound together as a program object)
1146         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1147         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1148         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1149
1150         // the second pretext is the mode (for example a light source)
1151         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1152         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1153         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1154         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1155
1156         // now add all the permutation pretexts
1157         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1158         {
1159                 if (permutation & (1ll<<i))
1160                 {
1161                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1162                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1163                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1164                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1165                 }
1166                 else
1167                 {
1168                         // keep line numbers correct
1169                         vertstrings_list[vertstrings_count++] = "\n";
1170                         geomstrings_list[geomstrings_count++] = "\n";
1171                         fragstrings_list[fragstrings_count++] = "\n";
1172                 }
1173         }
1174
1175         // add static parms
1176         R_CompileShader_AddStaticParms(mode, permutation);
1177         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         vertstrings_count += shaderstaticparms_count;
1179         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180         geomstrings_count += shaderstaticparms_count;
1181         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182         fragstrings_count += shaderstaticparms_count;
1183
1184         // now append the shader text itself
1185         vertstrings_list[vertstrings_count++] = sourcestring;
1186         geomstrings_list[geomstrings_count++] = sourcestring;
1187         fragstrings_list[fragstrings_count++] = sourcestring;
1188
1189         // compile the shader program
1190         if (vertstrings_count + geomstrings_count + fragstrings_count)
1191                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1192         if (p->program)
1193         {
1194                 CHECKGLERROR
1195                 qglUseProgram(p->program);CHECKGLERROR
1196                 // look up all the uniform variable names we care about, so we don't
1197                 // have to look them up every time we set them
1198
1199 #if 0
1200                 // debugging aid
1201                 {
1202                         GLint activeuniformindex = 0;
1203                         GLint numactiveuniforms = 0;
1204                         char uniformname[128];
1205                         GLsizei uniformnamelength = 0;
1206                         GLint uniformsize = 0;
1207                         GLenum uniformtype = 0;
1208                         memset(uniformname, 0, sizeof(uniformname));
1209                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1210                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1211                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1212                         {
1213                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1214                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1215                         }
1216                 }
1217 #endif
1218
1219                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1220                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1221                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1222                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1223                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1224                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1225                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1226                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1227                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1228                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1229                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1230                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1231                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1232                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1233                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1234                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1235                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1236                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1237                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1238                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1239                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1240                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1241                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1242                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1243                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1244                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1245                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1246                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1247                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1248                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1249                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1250                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1251                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1252                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1253                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1254                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1255                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1256                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1257                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1258                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1259                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1260                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1261                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1262                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1263                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1264                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1265                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1266                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1267                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1268                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1269                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1270                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1271                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1272                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1273                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1274                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1275                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1276                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1277                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1278                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1279                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1280                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1281                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1282                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1283                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1284                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1285                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1286                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1287                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1288                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1289                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1290                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1291                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1292                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1293                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1294                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1295                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1296                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1297                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1298                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1299                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1300                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1301                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1302                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1303                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1304                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1305                 // initialize the samplers to refer to the texture units we use
1306                 p->tex_Texture_First = -1;
1307                 p->tex_Texture_Second = -1;
1308                 p->tex_Texture_GammaRamps = -1;
1309                 p->tex_Texture_Normal = -1;
1310                 p->tex_Texture_Color = -1;
1311                 p->tex_Texture_Gloss = -1;
1312                 p->tex_Texture_Glow = -1;
1313                 p->tex_Texture_SecondaryNormal = -1;
1314                 p->tex_Texture_SecondaryColor = -1;
1315                 p->tex_Texture_SecondaryGloss = -1;
1316                 p->tex_Texture_SecondaryGlow = -1;
1317                 p->tex_Texture_Pants = -1;
1318                 p->tex_Texture_Shirt = -1;
1319                 p->tex_Texture_FogHeightTexture = -1;
1320                 p->tex_Texture_FogMask = -1;
1321                 p->tex_Texture_Lightmap = -1;
1322                 p->tex_Texture_Deluxemap = -1;
1323                 p->tex_Texture_Attenuation = -1;
1324                 p->tex_Texture_Cube = -1;
1325                 p->tex_Texture_Refraction = -1;
1326                 p->tex_Texture_Reflection = -1;
1327                 p->tex_Texture_ShadowMap2D = -1;
1328                 p->tex_Texture_CubeProjection = -1;
1329                 p->tex_Texture_ScreenNormalMap = -1;
1330                 p->tex_Texture_ScreenDiffuse = -1;
1331                 p->tex_Texture_ScreenSpecular = -1;
1332                 p->tex_Texture_ReflectMask = -1;
1333                 p->tex_Texture_ReflectCube = -1;
1334                 p->tex_Texture_BounceGrid = -1;
1335                 // bind the texture samplers in use
1336                 sampler = 0;
1337                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1338                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1339                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1340                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1341                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1342                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1343                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1344                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1345                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1346                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1347                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1348                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1349                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1350                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1351                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1352                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1353                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1354                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1355                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1356                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1357                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1358                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1359                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1360                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1361                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1362                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1363                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1364                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1365                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1366                 // get the uniform block indices so we can bind them
1367 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1368                 if (vid.support.arb_uniform_buffer_object)
1369                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1370                 else
1371 #endif
1372                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1373                 // clear the uniform block bindings
1374                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1375                 // bind the uniform blocks in use
1376                 ubibind = 0;
1377 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1378                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1379 #endif
1380                 // we're done compiling and setting up the shader, at least until it is used
1381                 CHECKGLERROR
1382                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1383         }
1384         else
1385                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1386
1387         // free the strings
1388         if (sourcestring)
1389                 Mem_Free(sourcestring);
1390 }
1391
1392 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1393 {
1394         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1395         if (r_glsl_permutation != perm)
1396         {
1397                 r_glsl_permutation = perm;
1398                 if (!r_glsl_permutation->program)
1399                 {
1400                         if (!r_glsl_permutation->compiled)
1401                         {
1402                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1403                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1404                         }
1405                         if (!r_glsl_permutation->program)
1406                         {
1407                                 // remove features until we find a valid permutation
1408                                 int i;
1409                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1410                                 {
1411                                         // reduce i more quickly whenever it would not remove any bits
1412                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1413                                         if (!(permutation & j))
1414                                                 continue;
1415                                         permutation -= j;
1416                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1417                                         if (!r_glsl_permutation->compiled)
1418                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1419                                         if (r_glsl_permutation->program)
1420                                                 break;
1421                                 }
1422                                 if (i >= SHADERPERMUTATION_COUNT)
1423                                 {
1424                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1425                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1426                                         qglUseProgram(0);CHECKGLERROR
1427                                         return; // no bit left to clear, entire mode is broken
1428                                 }
1429                         }
1430                 }
1431                 CHECKGLERROR
1432                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1433         }
1434         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1435         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1436         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1437         CHECKGLERROR
1438 }
1439
1440 #ifdef SUPPORTD3D
1441
1442 #ifdef SUPPORTD3D
1443 #include <d3d9.h>
1444 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1445 extern D3DCAPS9 vid_d3d9caps;
1446 #endif
1447
1448 struct r_hlsl_permutation_s;
1449 typedef struct r_hlsl_permutation_s
1450 {
1451         /// hash lookup data
1452         struct r_hlsl_permutation_s *hashnext;
1453         unsigned int mode;
1454         dpuint64 permutation;
1455
1456         /// indicates if we have tried compiling this permutation already
1457         qboolean compiled;
1458         /// NULL if compilation failed
1459         IDirect3DVertexShader9 *vertexshader;
1460         IDirect3DPixelShader9 *pixelshader;
1461 }
1462 r_hlsl_permutation_t;
1463
1464 typedef enum D3DVSREGISTER_e
1465 {
1466         D3DVSREGISTER_TexMatrix = 0, // float4x4
1467         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1468         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1469         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1470         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1471         D3DVSREGISTER_ModelToLight = 20, // float4x4
1472         D3DVSREGISTER_EyePosition = 24,
1473         D3DVSREGISTER_FogPlane = 25,
1474         D3DVSREGISTER_LightDir = 26,
1475         D3DVSREGISTER_LightPosition = 27,
1476 }
1477 D3DVSREGISTER_t;
1478
1479 typedef enum D3DPSREGISTER_e
1480 {
1481         D3DPSREGISTER_Alpha = 0,
1482         D3DPSREGISTER_BloomBlur_Parameters = 1,
1483         D3DPSREGISTER_ClientTime = 2,
1484         D3DPSREGISTER_Color_Ambient = 3,
1485         D3DPSREGISTER_Color_Diffuse = 4,
1486         D3DPSREGISTER_Color_Specular = 5,
1487         D3DPSREGISTER_Color_Glow = 6,
1488         D3DPSREGISTER_Color_Pants = 7,
1489         D3DPSREGISTER_Color_Shirt = 8,
1490         D3DPSREGISTER_DeferredColor_Ambient = 9,
1491         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1492         D3DPSREGISTER_DeferredColor_Specular = 11,
1493         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1494         D3DPSREGISTER_DeferredMod_Specular = 13,
1495         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1496         D3DPSREGISTER_EyePosition = 15, // unused
1497         D3DPSREGISTER_FogColor = 16,
1498         D3DPSREGISTER_FogHeightFade = 17,
1499         D3DPSREGISTER_FogPlane = 18,
1500         D3DPSREGISTER_FogPlaneViewDist = 19,
1501         D3DPSREGISTER_FogRangeRecip = 20,
1502         D3DPSREGISTER_LightColor = 21,
1503         D3DPSREGISTER_LightDir = 22, // unused
1504         D3DPSREGISTER_LightPosition = 23,
1505         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1506         D3DPSREGISTER_PixelSize = 25,
1507         D3DPSREGISTER_ReflectColor = 26,
1508         D3DPSREGISTER_ReflectFactor = 27,
1509         D3DPSREGISTER_ReflectOffset = 28,
1510         D3DPSREGISTER_RefractColor = 29,
1511         D3DPSREGISTER_Saturation = 30,
1512         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1513         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1514         D3DPSREGISTER_ScreenToDepth = 33,
1515         D3DPSREGISTER_ShadowMap_Parameters = 34,
1516         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1517         D3DPSREGISTER_SpecularPower = 36,
1518         D3DPSREGISTER_UserVec1 = 37,
1519         D3DPSREGISTER_UserVec2 = 38,
1520         D3DPSREGISTER_UserVec3 = 39,
1521         D3DPSREGISTER_UserVec4 = 40,
1522         D3DPSREGISTER_ViewTintColor = 41,
1523         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1524         D3DPSREGISTER_BloomColorSubtract = 43,
1525         D3DPSREGISTER_ViewToLight = 44, // float4x4
1526         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1527         D3DPSREGISTER_NormalmapScrollBlend = 52,
1528         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1529         D3DPSREGISTER_OffsetMapping_Bias = 54,
1530         // next at 54
1531 }
1532 D3DPSREGISTER_t;
1533
1534 /// information about each possible shader permutation
1535 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1536 /// currently selected permutation
1537 r_hlsl_permutation_t *r_hlsl_permutation;
1538 /// storage for permutations linked in the hash table
1539 memexpandablearray_t r_hlsl_permutationarray;
1540
1541 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1542 {
1543         //unsigned int hashdepth = 0;
1544         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1545         r_hlsl_permutation_t *p;
1546         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1547         {
1548                 if (p->mode == mode && p->permutation == permutation)
1549                 {
1550                         //if (hashdepth > 10)
1551                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1552                         return p;
1553                 }
1554                 //hashdepth++;
1555         }
1556         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1557         p->mode = mode;
1558         p->permutation = permutation;
1559         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1560         r_hlsl_permutationhash[mode][hashindex] = p;
1561         //if (hashdepth > 10)
1562         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1563         return p;
1564 }
1565
1566 #include <d3dx9.h>
1567 //#include <d3dx9shader.h>
1568 //#include <d3dx9mesh.h>
1569
1570 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1571 {
1572         DWORD *vsbin = NULL;
1573         DWORD *psbin = NULL;
1574         fs_offset_t vsbinsize;
1575         fs_offset_t psbinsize;
1576 //      IDirect3DVertexShader9 *vs = NULL;
1577 //      IDirect3DPixelShader9 *ps = NULL;
1578         ID3DXBuffer *vslog = NULL;
1579         ID3DXBuffer *vsbuffer = NULL;
1580         ID3DXConstantTable *vsconstanttable = NULL;
1581         ID3DXBuffer *pslog = NULL;
1582         ID3DXBuffer *psbuffer = NULL;
1583         ID3DXConstantTable *psconstanttable = NULL;
1584         int vsresult = 0;
1585         int psresult = 0;
1586         char temp[MAX_INPUTLINE];
1587         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1588         char vabuf[1024];
1589         qboolean debugshader = gl_paranoid.integer != 0;
1590         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1592         if (!debugshader)
1593         {
1594                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1595                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1596         }
1597         if ((!vsbin && vertstring) || (!psbin && fragstring))
1598         {
1599                 const char* dllnames_d3dx9 [] =
1600                 {
1601                         "d3dx9_43.dll",
1602                         "d3dx9_42.dll",
1603                         "d3dx9_41.dll",
1604                         "d3dx9_40.dll",
1605                         "d3dx9_39.dll",
1606                         "d3dx9_38.dll",
1607                         "d3dx9_37.dll",
1608                         "d3dx9_36.dll",
1609                         "d3dx9_35.dll",
1610                         "d3dx9_34.dll",
1611                         "d3dx9_33.dll",
1612                         "d3dx9_32.dll",
1613                         "d3dx9_31.dll",
1614                         "d3dx9_30.dll",
1615                         "d3dx9_29.dll",
1616                         "d3dx9_28.dll",
1617                         "d3dx9_27.dll",
1618                         "d3dx9_26.dll",
1619                         "d3dx9_25.dll",
1620                         "d3dx9_24.dll",
1621                         NULL
1622                 };
1623                 dllhandle_t d3dx9_dll = NULL;
1624                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1626                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1627                 dllfunction_t d3dx9_dllfuncs[] =
1628                 {
1629                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1630                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1631                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1632                         {NULL, NULL}
1633                 };
1634                 // 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...
1635 #ifndef ID3DXBuffer_GetBufferPointer
1636 #if !defined(__cplusplus) || defined(CINTERFACE)
1637 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1638 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1639 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1640 #else
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1643 #define ID3DXBuffer_Release(p)            (p)->Release()
1644 #endif
1645 #endif
1646                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1647                 {
1648                         DWORD shaderflags = 0;
1649                         if (debugshader)
1650                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1651                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1652                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1653                         if (vertstring && vertstring[0])
1654                         {
1655                                 if (debugshader)
1656                                 {
1657                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1658                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1659                                 }
1660                                 else
1661                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1662                                 if (vsbuffer)
1663                                 {
1664                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1665                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1666                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1667                                         ID3DXBuffer_Release(vsbuffer);
1668                                 }
1669                                 if (vslog)
1670                                 {
1671                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1672                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1673                                         ID3DXBuffer_Release(vslog);
1674                                 }
1675                         }
1676                         if (fragstring && fragstring[0])
1677                         {
1678                                 if (debugshader)
1679                                 {
1680                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1681                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1682                                 }
1683                                 else
1684                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1685                                 if (psbuffer)
1686                                 {
1687                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1688                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1689                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1690                                         ID3DXBuffer_Release(psbuffer);
1691                                 }
1692                                 if (pslog)
1693                                 {
1694                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1695                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1696                                         ID3DXBuffer_Release(pslog);
1697                                 }
1698                         }
1699                         Sys_UnloadLibrary(&d3dx9_dll);
1700                 }
1701                 else
1702                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1703         }
1704         if (vsbin && psbin)
1705         {
1706                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1707                 if (FAILED(vsresult))
1708                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1709                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1710                 if (FAILED(psresult))
1711                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1712         }
1713         // free the shader data
1714         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1715         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1716 }
1717
1718 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1719 {
1720         int i;
1721         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1722         int vertstring_length = 0;
1723         int geomstring_length = 0;
1724         int fragstring_length = 0;
1725         char *t;
1726         char *sourcestring;
1727         char *vertstring, *geomstring, *fragstring;
1728         char permutationname[256];
1729         char cachename[256];
1730         int vertstrings_count = 0;
1731         int geomstrings_count = 0;
1732         int fragstrings_count = 0;
1733         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1736
1737         if (p->compiled)
1738                 return;
1739         p->compiled = true;
1740         p->vertexshader = NULL;
1741         p->pixelshader = NULL;
1742
1743         permutationname[0] = 0;
1744         cachename[0] = 0;
1745         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1746
1747         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1748         strlcat(cachename, "hlsl/", sizeof(cachename));
1749
1750         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1751         vertstrings_count = 0;
1752         geomstrings_count = 0;
1753         fragstrings_count = 0;
1754         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1755         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1756         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1757
1758         // the first pretext is which type of shader to compile as
1759         // (later these will all be bound together as a program object)
1760         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1761         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1762         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1763
1764         // the second pretext is the mode (for example a light source)
1765         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1766         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1767         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1768         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1769         strlcat(cachename, modeinfo->name, sizeof(cachename));
1770
1771         // now add all the permutation pretexts
1772         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1773         {
1774                 if (permutation & (1ll<<i))
1775                 {
1776                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1777                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1778                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1779                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1780                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1781                 }
1782                 else
1783                 {
1784                         // keep line numbers correct
1785                         vertstrings_list[vertstrings_count++] = "\n";
1786                         geomstrings_list[geomstrings_count++] = "\n";
1787                         fragstrings_list[fragstrings_count++] = "\n";
1788                 }
1789         }
1790
1791         // add static parms
1792         R_CompileShader_AddStaticParms(mode, permutation);
1793         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         vertstrings_count += shaderstaticparms_count;
1795         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796         geomstrings_count += shaderstaticparms_count;
1797         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798         fragstrings_count += shaderstaticparms_count;
1799
1800         // replace spaces in the cachename with _ characters
1801         for (i = 0;cachename[i];i++)
1802                 if (cachename[i] == ' ')
1803                         cachename[i] = '_';
1804
1805         // now append the shader text itself
1806         vertstrings_list[vertstrings_count++] = sourcestring;
1807         geomstrings_list[geomstrings_count++] = sourcestring;
1808         fragstrings_list[fragstrings_count++] = sourcestring;
1809
1810         vertstring_length = 0;
1811         for (i = 0;i < vertstrings_count;i++)
1812                 vertstring_length += (int)strlen(vertstrings_list[i]);
1813         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1814         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1815                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1816
1817         geomstring_length = 0;
1818         for (i = 0;i < geomstrings_count;i++)
1819                 geomstring_length += (int)strlen(geomstrings_list[i]);
1820         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1821         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1822                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1823
1824         fragstring_length = 0;
1825         for (i = 0;i < fragstrings_count;i++)
1826                 fragstring_length += (int)strlen(fragstrings_list[i]);
1827         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1828         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1829                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1830
1831         // try to load the cached shader, or generate one
1832         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1833
1834         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1835                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1836         else
1837                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1838
1839         // free the strings
1840         if (vertstring)
1841                 Mem_Free(vertstring);
1842         if (geomstring)
1843                 Mem_Free(geomstring);
1844         if (fragstring)
1845                 Mem_Free(fragstring);
1846         if (sourcestring)
1847                 Mem_Free(sourcestring);
1848 }
1849
1850 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1851 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1852 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);}
1853 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);}
1854 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);}
1855 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);}
1856
1857 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1858 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1859 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);}
1860 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);}
1861 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);}
1862 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);}
1863
1864 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1865 {
1866         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1867         if (r_hlsl_permutation != perm)
1868         {
1869                 r_hlsl_permutation = perm;
1870                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1871                 {
1872                         if (!r_hlsl_permutation->compiled)
1873                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1874                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875                         {
1876                                 // remove features until we find a valid permutation
1877                                 int i;
1878                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879                                 {
1880                                         // reduce i more quickly whenever it would not remove any bits
1881                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1882                                         if (!(permutation & j))
1883                                                 continue;
1884                                         permutation -= j;
1885                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1886                                         if (!r_hlsl_permutation->compiled)
1887                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1888                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1889                                                 break;
1890                                 }
1891                                 if (i >= SHADERPERMUTATION_COUNT)
1892                                 {
1893                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1894                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1895                                         return; // no bit left to clear, entire mode is broken
1896                                 }
1897                         }
1898                 }
1899                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1900                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1901         }
1902         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1903         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1904         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1905 }
1906 #endif
1907
1908 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1909 {
1910         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1911         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1912         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1913         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1914 }
1915
1916 void R_GLSL_Restart_f(void)
1917 {
1918         unsigned int i, limit;
1919         switch(vid.renderpath)
1920         {
1921         case RENDERPATH_D3D9:
1922 #ifdef SUPPORTD3D
1923                 {
1924                         r_hlsl_permutation_t *p;
1925                         r_hlsl_permutation = NULL;
1926                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1927                         for (i = 0;i < limit;i++)
1928                         {
1929                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1930                                 {
1931                                         if (p->vertexshader)
1932                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1933                                         if (p->pixelshader)
1934                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1935                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1936                                 }
1937                         }
1938                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1939                 }
1940 #endif
1941                 break;
1942         case RENDERPATH_D3D10:
1943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_D3D11:
1946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947                 break;
1948         case RENDERPATH_GL20:
1949         case RENDERPATH_GLES2:
1950                 {
1951                         r_glsl_permutation_t *p;
1952                         r_glsl_permutation = NULL;
1953                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1954                         for (i = 0;i < limit;i++)
1955                         {
1956                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1957                                 {
1958                                         GL_Backend_FreeProgram(p->program);
1959                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1960                                 }
1961                         }
1962                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1963                 }
1964                 break;
1965         case RENDERPATH_GL11:
1966         case RENDERPATH_GL13:
1967         case RENDERPATH_GLES1:
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 break;
1971         }
1972 }
1973
1974 static void R_GLSL_DumpShader_f(void)
1975 {
1976         int i, language, mode, dupe;
1977         char *text;
1978         shadermodeinfo_t *modeinfo;
1979         qfile_t *file;
1980
1981         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1982         {
1983                 modeinfo = shadermodeinfo[language];
1984                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1985                 {
1986                         // don't dump the same file multiple times (most or all shaders come from the same file)
1987                         for (dupe = mode - 1;dupe >= 0;dupe--)
1988                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1989                                         break;
1990                         if (dupe >= 0)
1991                                 continue;
1992                         text = modeinfo[mode].builtinstring;
1993                         if (!text)
1994                                 continue;
1995                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1996                         if (file)
1997                         {
1998                                 FS_Print(file, "/* The engine may define the following macros:\n");
1999                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2000                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2001                                         FS_Print(file, modeinfo[i].pretext);
2002                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2003                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2004                                 FS_Print(file, "*/\n");
2005                                 FS_Print(file, text);
2006                                 FS_Close(file);
2007                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2008                         }
2009                         else
2010                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2011                 }
2012         }
2013 }
2014
2015 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2016 {
2017         dpuint64 permutation = 0;
2018         if (r_trippy.integer && !notrippy)
2019                 permutation |= SHADERPERMUTATION_TRIPPY;
2020         permutation |= SHADERPERMUTATION_VIEWTINT;
2021         if (first)
2022                 permutation |= SHADERPERMUTATION_DIFFUSE;
2023         if (second)
2024                 permutation |= SHADERPERMUTATION_SPECULAR;
2025         if (texturemode == GL_MODULATE)
2026                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2027         else if (texturemode == GL_ADD)
2028                 permutation |= SHADERPERMUTATION_GLOW;
2029         else if (texturemode == GL_DECAL)
2030                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2031         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2032                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2033         if (suppresstexalpha)
2034                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2035         if (!second)
2036                 texturemode = GL_MODULATE;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTD3D
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2044                 R_Mesh_TexBind(GL20TU_FIRST , first );
2045                 R_Mesh_TexBind(GL20TU_SECOND, second);
2046                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2047                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2048 #endif
2049                 break;
2050         case RENDERPATH_D3D10:
2051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052                 break;
2053         case RENDERPATH_D3D11:
2054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2055                 break;
2056         case RENDERPATH_GL20:
2057         case RENDERPATH_GLES2:
2058                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2059                 if (r_glsl_permutation->tex_Texture_First >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2061                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2062                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2063                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2064                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2065                 break;
2066         case RENDERPATH_GL13:
2067         case RENDERPATH_GLES1:
2068                 R_Mesh_TexBind(0, first );
2069                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2070                 R_Mesh_TexMatrix(0, NULL);
2071                 R_Mesh_TexBind(1, second);
2072                 if (second)
2073                 {
2074                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2075                         R_Mesh_TexMatrix(1, NULL);
2076                 }
2077                 break;
2078         case RENDERPATH_GL11:
2079                 R_Mesh_TexBind(0, first );
2080                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2081                 R_Mesh_TexMatrix(0, NULL);
2082                 break;
2083         case RENDERPATH_SOFT:
2084                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2085                 R_Mesh_TexBind(GL20TU_FIRST , first );
2086                 R_Mesh_TexBind(GL20TU_SECOND, second);
2087                 break;
2088         }
2089 }
2090
2091 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2092 {
2093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2094 }
2095
2096 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2097 {
2098         dpuint64 permutation = 0;
2099         if (r_trippy.integer && !notrippy)
2100                 permutation |= SHADERPERMUTATION_TRIPPY;
2101         if (depthrgb)
2102                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2103         if (skeletal)
2104                 permutation |= SHADERPERMUTATION_SKELETAL;
2105
2106         if (vid.allowalphatocoverage)
2107                 GL_AlphaToCoverage(false);
2108         switch (vid.renderpath)
2109         {
2110         case RENDERPATH_D3D9:
2111 #ifdef SUPPORTD3D
2112                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2113 #endif
2114                 break;
2115         case RENDERPATH_D3D10:
2116                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2117                 break;
2118         case RENDERPATH_D3D11:
2119                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2120                 break;
2121         case RENDERPATH_GL20:
2122         case RENDERPATH_GLES2:
2123                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2124 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2125                 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);
2126 #endif
2127                 break;
2128         case RENDERPATH_GL13:
2129         case RENDERPATH_GLES1:
2130                 R_Mesh_TexBind(0, 0);
2131                 R_Mesh_TexBind(1, 0);
2132                 break;
2133         case RENDERPATH_GL11:
2134                 R_Mesh_TexBind(0, 0);
2135                 break;
2136         case RENDERPATH_SOFT:
2137                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2138                 break;
2139         }
2140 }
2141
2142 #define BLENDFUNC_ALLOWS_COLORMOD      1
2143 #define BLENDFUNC_ALLOWS_FOG           2
2144 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2145 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2146 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2147 static int R_BlendFuncFlags(int src, int dst)
2148 {
2149         int r = 0;
2150
2151         // a blendfunc allows colormod if:
2152         // a) it can never keep the destination pixel invariant, or
2153         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2154         // this is to prevent unintended side effects from colormod
2155
2156         // a blendfunc allows fog if:
2157         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2158         // this is to prevent unintended side effects from fog
2159
2160         // these checks are the output of fogeval.pl
2161
2162         r |= BLENDFUNC_ALLOWS_COLORMOD;
2163         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2164         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2165         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2167         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2172         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2176         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2181         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2183         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184
2185         return r;
2186 }
2187
2188 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2189 {
2190         // select a permutation of the lighting shader appropriate to this
2191         // combination of texture, entity, light source, and fogging, only use the
2192         // minimum features necessary to avoid wasting rendering time in the
2193         // fragment shader on features that are not being used
2194         dpuint64 permutation = 0;
2195         unsigned int mode = 0;
2196         int blendfuncflags;
2197         texture_t *t = rsurface.texture;
2198         float m16f[16];
2199         matrix4x4_t tempmatrix;
2200         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2201         if (r_trippy.integer && !notrippy)
2202                 permutation |= SHADERPERMUTATION_TRIPPY;
2203         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2204                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2205         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2206                 permutation |= SHADERPERMUTATION_OCCLUDE;
2207         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2208                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2209         if (rsurfacepass == RSURFPASS_BACKGROUND)
2210         {
2211                 // distorted background
2212                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2213                 {
2214                         mode = SHADERMODE_WATER;
2215                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2216                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2217                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2218                         {
2219                                 // this is the right thing to do for wateralpha
2220                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2221                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2222                         }
2223                         else
2224                         {
2225                                 // this is the right thing to do for entity alpha
2226                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2227                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228                         }
2229                 }
2230                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2231                 {
2232                         mode = SHADERMODE_REFRACTION;
2233                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2234                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2235                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2236                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237                 }
2238                 else
2239                 {
2240                         mode = SHADERMODE_GENERIC;
2241                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2242                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2244                 }
2245                 if (vid.allowalphatocoverage)
2246                         GL_AlphaToCoverage(false);
2247         }
2248         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2249         {
2250                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2251                 {
2252                         switch(t->offsetmapping)
2253                         {
2254                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2255                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_OFF: break;
2258                         }
2259                 }
2260                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2261                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2262                 // normalmap (deferred prepass), may use alpha test on diffuse
2263                 mode = SHADERMODE_DEFERREDGEOMETRY;
2264                 GL_BlendFunc(GL_ONE, GL_ZERO);
2265                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2266                 if (vid.allowalphatocoverage)
2267                         GL_AlphaToCoverage(false);
2268         }
2269         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2270         {
2271                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2272                 {
2273                         switch(t->offsetmapping)
2274                         {
2275                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2276                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2277                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278                         case OFFSETMAPPING_OFF: break;
2279                         }
2280                 }
2281                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2282                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2283                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2284                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2285                 // light source
2286                 mode = SHADERMODE_LIGHTSOURCE;
2287                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2288                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2289                 if (VectorLength2(rtlightdiffuse) > 0)
2290                         permutation |= SHADERPERMUTATION_DIFFUSE;
2291                 if (VectorLength2(rtlightspecular) > 0)
2292                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2293                 if (r_refdef.fogenabled)
2294                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2295                 if (t->colormapping)
2296                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2297                 if (r_shadow_usingshadowmap2d)
2298                 {
2299                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2300                         if(r_shadow_shadowmapvsdct)
2301                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2302
2303                         if (r_shadow_shadowmap2ddepthbuffer)
2304                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2305                 }
2306                 if (t->reflectmasktexture)
2307                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2308                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2309                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2310                 if (vid.allowalphatocoverage)
2311                         GL_AlphaToCoverage(false);
2312         }
2313         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2314         {
2315                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2316                 {
2317                         switch(t->offsetmapping)
2318                         {
2319                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2320                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2321                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322                         case OFFSETMAPPING_OFF: break;
2323                         }
2324                 }
2325                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2326                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2327                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2328                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2329                 // directional model lighting
2330                 mode = SHADERMODE_LIGHTDIRECTION;
2331                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2332                         permutation |= SHADERPERMUTATION_GLOW;
2333                 if (VectorLength2(t->render_modellight_diffuse))
2334                         permutation |= SHADERPERMUTATION_DIFFUSE;
2335                 if (VectorLength2(t->render_modellight_specular) > 0)
2336                         permutation |= SHADERPERMUTATION_SPECULAR;
2337                 if (r_refdef.fogenabled)
2338                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2339                 if (t->colormapping)
2340                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2341                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2342                 {
2343                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2344                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2345
2346                         if (r_shadow_shadowmap2ddepthbuffer)
2347                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2348                 }
2349                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2350                         permutation |= SHADERPERMUTATION_REFLECTION;
2351                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2352                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2353                 if (t->reflectmasktexture)
2354                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2355                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2356                 {
2357                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2358                         if (r_shadow_bouncegrid_state.directional)
2359                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2360                 }
2361                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2362                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2363                 // when using alphatocoverage, we don't need alphakill
2364                 if (vid.allowalphatocoverage)
2365                 {
2366                         if (r_transparent_alphatocoverage.integer)
2367                         {
2368                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2369                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2370                         }
2371                         else
2372                                 GL_AlphaToCoverage(false);
2373                 }
2374         }
2375         else
2376         {
2377                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2378                 {
2379                         switch(t->offsetmapping)
2380                         {
2381                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2382                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2383                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384                         case OFFSETMAPPING_OFF: break;
2385                         }
2386                 }
2387                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2388                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2389                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2390                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2391                 // lightmapped wall
2392                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2393                         permutation |= SHADERPERMUTATION_GLOW;
2394                 if (r_refdef.fogenabled)
2395                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2396                 if (t->colormapping)
2397                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2398                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2399                 {
2400                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2401                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2402
2403                         if (r_shadow_shadowmap2ddepthbuffer)
2404                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2405                 }
2406                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2407                         permutation |= SHADERPERMUTATION_REFLECTION;
2408                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2409                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2410                 if (t->reflectmasktexture)
2411                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2412                 if (FAKELIGHT_ENABLED)
2413                 {
2414                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2415                         mode = SHADERMODE_FAKELIGHT;
2416                         permutation |= SHADERPERMUTATION_DIFFUSE;
2417                         if (VectorLength2(t->render_lightmap_specular) > 0)
2418                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2419                 }
2420                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2421                 {
2422                         // deluxemapping (light direction texture)
2423                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2424                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2425                         else
2426                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2427                         permutation |= SHADERPERMUTATION_DIFFUSE;
2428                         if (VectorLength2(t->render_lightmap_specular) > 0)
2429                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2430                 }
2431                 else if (r_glsl_deluxemapping.integer >= 2)
2432                 {
2433                         // fake deluxemapping (uniform light direction in tangentspace)
2434                         if (rsurface.uselightmaptexture)
2435                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2436                         else
2437                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2438                         permutation |= SHADERPERMUTATION_DIFFUSE;
2439                         if (VectorLength2(t->render_lightmap_specular) > 0)
2440                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2441                 }
2442                 else if (rsurface.uselightmaptexture)
2443                 {
2444                         // ordinary lightmapping (q1bsp, q3bsp)
2445                         mode = SHADERMODE_LIGHTMAP;
2446                 }
2447                 else
2448                 {
2449                         // ordinary vertex coloring (q3bsp)
2450                         mode = SHADERMODE_VERTEXCOLOR;
2451                 }
2452                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2453                 {
2454                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2455                         if (r_shadow_bouncegrid_state.directional)
2456                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2457                 }
2458                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2459                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2460                 // when using alphatocoverage, we don't need alphakill
2461                 if (vid.allowalphatocoverage)
2462                 {
2463                         if (r_transparent_alphatocoverage.integer)
2464                         {
2465                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2466                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2467                         }
2468                         else
2469                                 GL_AlphaToCoverage(false);
2470                 }
2471         }
2472         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2473                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2474         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2475                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2476         switch(vid.renderpath)
2477         {
2478         case RENDERPATH_D3D9:
2479 #ifdef SUPPORTD3D
2480                 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);
2481                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2482                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2483                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2484                 if (mode == SHADERMODE_LIGHTSOURCE)
2485                 {
2486                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2487                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2488                 }
2489                 else
2490                 {
2491                         if (mode == SHADERMODE_LIGHTDIRECTION)
2492                         {
2493                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2494                         }
2495                 }
2496                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2497                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2498                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2499                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2500                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2501
2502                 if (mode == SHADERMODE_LIGHTSOURCE)
2503                 {
2504                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2505                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2506                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2507                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2508                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2509
2510                         // additive passes are only darkened by fog, not tinted
2511                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2512                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2513                 }
2514                 else
2515                 {
2516                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2517                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2518                         if (mode == SHADERMODE_FLATCOLOR)
2519                         {
2520                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2521                         }
2522                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2523                         {
2524                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2525                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2526                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2527                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2528                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2529                         }
2530                         else
2531                         {
2532                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2533                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2534                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2535                         }
2536                         // additive passes are only darkened by fog, not tinted
2537                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2538                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2539                         else
2540                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2541                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2542                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2543                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2544                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2545                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2546                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2547                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2548                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2549                         if (mode == SHADERMODE_WATER)
2550                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2551                 }
2552                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2553                 {
2554                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2555                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2556                 }
2557                 else
2558                 {
2559                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2560                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2561                 }
2562                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2563                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2564                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2565                 if (t->pantstexture)
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2567                 else
2568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2569                 if (t->shirttexture)
2570                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2571                 else
2572                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2573                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2574                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2575                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2576                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2577                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2578                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2579                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2580                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2581                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2582                         );
2583                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2584                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2585                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2586                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2587
2588                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2589                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2590                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2591                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2592                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2593                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2594                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2595                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2596                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2597                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2598                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2599                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2600                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2601                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2602                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2603                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2604                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2605                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2606                 {
2607                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2608                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2609                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2610                 }
2611                 else
2612                 {
2613                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2614                 }
2615 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2616                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2617                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2618                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2619                 {
2620                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2621                         if (rsurface.rtlight)
2622                         {
2623                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2624                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2625                         }
2626                 }
2627 #endif
2628                 break;
2629         case RENDERPATH_D3D10:
2630                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2631                 break;
2632         case RENDERPATH_D3D11:
2633                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2634                 break;
2635         case RENDERPATH_GL20:
2636         case RENDERPATH_GLES2:
2637                 if (!vid.useinterleavedarrays)
2638                 {
2639                         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);
2640                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2641                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2642                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2643                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2644                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2645                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2646                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2647                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2648                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2649                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2650                 }
2651                 else
2652                 {
2653                         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);
2654                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2655                 }
2656                 // this has to be after RSurf_PrepareVerticesForBatch
2657                 if (rsurface.batchskeletaltransform3x4buffer)
2658                         permutation |= SHADERPERMUTATION_SKELETAL;
2659                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2660 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2661                 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);
2662 #endif
2663                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2664                 if (mode == SHADERMODE_LIGHTSOURCE)
2665                 {
2666                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2667                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2668                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2669                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2670                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2671                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2672         
2673                         // additive passes are only darkened by fog, not tinted
2674                         if (r_glsl_permutation->loc_FogColor >= 0)
2675                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2676                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2677                 }
2678                 else
2679                 {
2680                         if (mode == SHADERMODE_FLATCOLOR)
2681                         {
2682                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2683                         }
2684                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2685                         {
2686                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2687                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2688                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2689                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2690                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2691                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2692                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2693                         }
2694                         else
2695                         {
2696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2697                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2698                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2699                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2700                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2701                         }
2702                         // additive passes are only darkened by fog, not tinted
2703                         if (r_glsl_permutation->loc_FogColor >= 0)
2704                         {
2705                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2706                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2707                                 else
2708                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2709                         }
2710                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2711                         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]);
2712                         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]);
2713                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2714                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2715                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2716                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2717                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2718                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2719                 }
2720                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2721                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2722                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2723                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2724                 {
2725                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2726                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2727                 }
2728                 else
2729                 {
2730                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2731                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2732                 }
2733
2734                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2735                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2736                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2737                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2738                 {
2739                         if (t->pantstexture)
2740                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2741                         else
2742                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2743                 }
2744                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2745                 {
2746                         if (t->shirttexture)
2747                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2748                         else
2749                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2750                 }
2751                 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]);
2752                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2753                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2754                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2755                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2756                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2757                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2758                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2759                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2760                         );
2761                 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);
2762                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2763                 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]);
2764                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2765                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2766                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2767
2768                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2769                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2770                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2771                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2772                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2773                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2774                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2775                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2779                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2780                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2781                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2782                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2783                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2784                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2785                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2786                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2787                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2788                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2789                 {
2790                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2791                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2792                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2793                 }
2794                 else
2795                 {
2796                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2797                 }
2798                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2799                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2800                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2801                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2802                 {
2803                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2804                         if (rsurface.rtlight)
2805                         {
2806                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2807                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2808                         }
2809                 }
2810                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2811                 CHECKGLERROR
2812                 break;
2813         case RENDERPATH_GL11:
2814         case RENDERPATH_GL13:
2815         case RENDERPATH_GLES1:
2816                 break;
2817         case RENDERPATH_SOFT:
2818                 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);
2819                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2820                 R_SetupShader_SetPermutationSoft(mode, permutation);
2821                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2822                 if (mode == SHADERMODE_LIGHTSOURCE)
2823                 {
2824                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2825                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2826                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2830         
2831                         // additive passes are only darkened by fog, not tinted
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2833                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2834                 }
2835                 else
2836                 {
2837                         if (mode == SHADERMODE_FLATCOLOR)
2838                         {
2839                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2840                         }
2841                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2842                         {
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2844                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2846                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2848                         }
2849                         else
2850                         {
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2854                         }
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2857                         // additive passes are only darkened by fog, not tinted
2858                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2860                         else
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2862                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2863                         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]);
2864                         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]);
2865                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2866                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2867                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2868                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2869                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2870                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2871                 }
2872                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2873                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2874                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2875                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2876                 {
2877                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2878                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2879                 }
2880                 else
2881                 {
2882                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2883                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2884                 }
2885
2886                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2887                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2888                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2890                 {
2891                         if (t->pantstexture)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2895                 }
2896                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2897                 {
2898                         if (t->shirttexture)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2902                 }
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2909                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2912                         );
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2915                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2916                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2917
2918                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2919                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2920                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2921                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2922                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2923                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2924                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2926                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2927                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2928                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2929                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2930                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2931                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2932                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2933                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2934                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2935                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2936                 {
2937                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2938                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2939                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2940                 }
2941                 else
2942                 {
2943                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2944                 }
2945 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2946                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2947                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2948                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2949                 {
2950                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2951                         if (rsurface.rtlight)
2952                         {
2953                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2954                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2955                         }
2956                 }
2957                 break;
2958         }
2959 }
2960
2961 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2962 {
2963         // select a permutation of the lighting shader appropriate to this
2964         // combination of texture, entity, light source, and fogging, only use the
2965         // minimum features necessary to avoid wasting rendering time in the
2966         // fragment shader on features that are not being used
2967         dpuint64 permutation = 0;
2968         unsigned int mode = 0;
2969         const float *lightcolorbase = rtlight->currentcolor;
2970         float ambientscale = rtlight->ambientscale;
2971         float diffusescale = rtlight->diffusescale;
2972         float specularscale = rtlight->specularscale;
2973         // this is the location of the light in view space
2974         vec3_t viewlightorigin;
2975         // this transforms from view space (camera) to light space (cubemap)
2976         matrix4x4_t viewtolight;
2977         matrix4x4_t lighttoview;
2978         float viewtolight16f[16];
2979         // light source
2980         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981         if (rtlight->currentcubemap != r_texture_whitecube)
2982                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983         if (diffusescale > 0)
2984                 permutation |= SHADERPERMUTATION_DIFFUSE;
2985         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987         if (r_shadow_usingshadowmap2d)
2988         {
2989                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990                 if (r_shadow_shadowmapvsdct)
2991                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2992
2993                 if (r_shadow_shadowmap2ddepthbuffer)
2994                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2995         }
2996         if (vid.allowalphatocoverage)
2997                 GL_AlphaToCoverage(false);
2998         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3001         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002         switch(vid.renderpath)
3003         {
3004         case RENDERPATH_D3D9:
3005 #ifdef SUPPORTD3D
3006                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3011                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3012                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3013                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3014                 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);
3015                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3017
3018                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3019                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3020                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3021                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3022                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3023 #endif
3024                 break;
3025         case RENDERPATH_D3D10:
3026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3027                 break;
3028         case RENDERPATH_D3D11:
3029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030                 break;
3031         case RENDERPATH_GL20:
3032         case RENDERPATH_GLES2:
3033                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3036                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3040                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3041                 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);
3042                 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]);
3043                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3044
3045                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3046                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3047                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3048                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3049                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3050                 break;
3051         case RENDERPATH_GL11:
3052         case RENDERPATH_GL13:
3053         case RENDERPATH_GLES1:
3054                 break;
3055         case RENDERPATH_SOFT:
3056                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3057                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3058                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3059                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3060                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3062                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3063                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3064                 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);
3065                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3066                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3067
3068                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3069                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3070                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3071                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3072                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3073                 break;
3074         }
3075 }
3076
3077 #define SKINFRAME_HASH 1024
3078
3079 typedef struct
3080 {
3081         unsigned int loadsequence; // incremented each level change
3082         memexpandablearray_t array;
3083         skinframe_t *hash[SKINFRAME_HASH];
3084 }
3085 r_skinframe_t;
3086 r_skinframe_t r_skinframe;
3087
3088 void R_SkinFrame_PrepareForPurge(void)
3089 {
3090         r_skinframe.loadsequence++;
3091         // wrap it without hitting zero
3092         if (r_skinframe.loadsequence >= 200)
3093                 r_skinframe.loadsequence = 1;
3094 }
3095
3096 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3097 {
3098         if (!skinframe)
3099                 return;
3100         // mark the skinframe as used for the purging code
3101         skinframe->loadsequence = r_skinframe.loadsequence;
3102 }
3103
3104 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3105 {
3106         if (s->merged == s->base)
3107                 s->merged = NULL;
3108         R_PurgeTexture(s->stain); s->stain = NULL;
3109         R_PurgeTexture(s->merged); s->merged = NULL;
3110         R_PurgeTexture(s->base); s->base = NULL;
3111         R_PurgeTexture(s->pants); s->pants = NULL;
3112         R_PurgeTexture(s->shirt); s->shirt = NULL;
3113         R_PurgeTexture(s->nmap); s->nmap = NULL;
3114         R_PurgeTexture(s->gloss); s->gloss = NULL;
3115         R_PurgeTexture(s->glow); s->glow = NULL;
3116         R_PurgeTexture(s->fog); s->fog = NULL;
3117         R_PurgeTexture(s->reflect); s->reflect = NULL;
3118         s->loadsequence = 0;
3119 }
3120
3121 void R_SkinFrame_Purge(void)
3122 {
3123         int i;
3124         skinframe_t *s;
3125         for (i = 0;i < SKINFRAME_HASH;i++)
3126         {
3127                 for (s = r_skinframe.hash[i];s;s = s->next)
3128                 {
3129                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3130                                 R_SkinFrame_PurgeSkinFrame(s);
3131                 }
3132         }
3133 }
3134
3135 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3136         skinframe_t *item;
3137         char basename[MAX_QPATH];
3138
3139         Image_StripImageExtension(name, basename, sizeof(basename));
3140
3141         if( last == NULL ) {
3142                 int hashindex;
3143                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3144                 item = r_skinframe.hash[hashindex];
3145         } else {
3146                 item = last->next;
3147         }
3148
3149         // linearly search through the hash bucket
3150         for( ; item ; item = item->next ) {
3151                 if( !strcmp( item->basename, basename ) ) {
3152                         return item;
3153                 }
3154         }
3155         return NULL;
3156 }
3157
3158 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3159 {
3160         skinframe_t *item;
3161         int hashindex;
3162         char basename[MAX_QPATH];
3163
3164         Image_StripImageExtension(name, basename, sizeof(basename));
3165
3166         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3168                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3169                         break;
3170
3171         if (!item)
3172         {
3173                 if (!add)
3174                         return NULL;
3175                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3176                 memset(item, 0, sizeof(*item));
3177                 strlcpy(item->basename, basename, sizeof(item->basename));
3178                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3179                 item->comparewidth = comparewidth;
3180                 item->compareheight = compareheight;
3181                 item->comparecrc = comparecrc;
3182                 item->next = r_skinframe.hash[hashindex];
3183                 r_skinframe.hash[hashindex] = item;
3184         }
3185         else if (textureflags & TEXF_FORCE_RELOAD)
3186         {
3187                 if (!add)
3188                         return NULL;
3189                 R_SkinFrame_PurgeSkinFrame(item);
3190         }
3191
3192         R_SkinFrame_MarkUsed(item);
3193         return item;
3194 }
3195
3196 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3197         { \
3198                 unsigned long long avgcolor[5], wsum; \
3199                 int pix, comp, w; \
3200                 avgcolor[0] = 0; \
3201                 avgcolor[1] = 0; \
3202                 avgcolor[2] = 0; \
3203                 avgcolor[3] = 0; \
3204                 avgcolor[4] = 0; \
3205                 wsum = 0; \
3206                 for(pix = 0; pix < cnt; ++pix) \
3207                 { \
3208                         w = 0; \
3209                         for(comp = 0; comp < 3; ++comp) \
3210                                 w += getpixel; \
3211                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3212                         { \
3213                                 ++wsum; \
3214                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3215                                 w = getpixel; \
3216                                 for(comp = 0; comp < 3; ++comp) \
3217                                         avgcolor[comp] += getpixel * w; \
3218                                 avgcolor[3] += w; \
3219                         } \
3220                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3221                         avgcolor[4] += getpixel; \
3222                 } \
3223                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3224                         avgcolor[3] = 1; \
3225                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3226                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3227                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3228                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3229         }
3230
3231 extern cvar_t gl_picmip;
3232 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3233 {
3234         int j;
3235         unsigned char *pixels;
3236         unsigned char *bumppixels;
3237         unsigned char *basepixels = NULL;
3238         int basepixels_width = 0;
3239         int basepixels_height = 0;
3240         skinframe_t *skinframe;
3241         rtexture_t *ddsbase = NULL;
3242         qboolean ddshasalpha = false;
3243         float ddsavgcolor[4];
3244         char basename[MAX_QPATH];
3245         int miplevel = R_PicmipForFlags(textureflags);
3246         int savemiplevel = miplevel;
3247         int mymiplevel;
3248         char vabuf[1024];
3249
3250         if (cls.state == ca_dedicated)
3251                 return NULL;
3252
3253         // return an existing skinframe if already loaded
3254         // if loading of the first image fails, don't make a new skinframe as it
3255         // would cause all future lookups of this to be missing
3256         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3257         if (skinframe && skinframe->base)
3258                 return skinframe;
3259
3260         Image_StripImageExtension(name, basename, sizeof(basename));
3261
3262         // check for DDS texture file first
3263         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3264         {
3265                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3266                 if (basepixels == NULL && fallbacknotexture)
3267                         basepixels = Image_GenerateNoTexture();
3268                 if (basepixels == NULL)
3269                         return NULL;
3270         }
3271
3272         // FIXME handle miplevel
3273
3274         if (developer_loading.integer)
3275                 Con_Printf("loading skin \"%s\"\n", name);
3276
3277         // we've got some pixels to store, so really allocate this new texture now
3278         if (!skinframe)
3279                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3280         textureflags &= ~TEXF_FORCE_RELOAD;
3281         skinframe->stain = NULL;
3282         skinframe->merged = NULL;
3283         skinframe->base = NULL;
3284         skinframe->pants = NULL;
3285         skinframe->shirt = NULL;
3286         skinframe->nmap = NULL;
3287         skinframe->gloss = NULL;
3288         skinframe->glow = NULL;
3289         skinframe->fog = NULL;
3290         skinframe->reflect = NULL;
3291         skinframe->hasalpha = false;
3292         // we could store the q2animname here too
3293
3294         if (ddsbase)
3295         {
3296                 skinframe->base = ddsbase;
3297                 skinframe->hasalpha = ddshasalpha;
3298                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3299                 if (r_loadfog && skinframe->hasalpha)
3300                         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);
3301                 //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]);
3302         }
3303         else
3304         {
3305                 basepixels_width = image_width;
3306                 basepixels_height = image_height;
3307                 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);
3308                 if (textureflags & TEXF_ALPHA)
3309                 {
3310                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3311                         {
3312                                 if (basepixels[j] < 255)
3313                                 {
3314                                         skinframe->hasalpha = true;
3315                                         break;
3316                                 }
3317                         }
3318                         if (r_loadfog && skinframe->hasalpha)
3319                         {
3320                                 // has transparent pixels
3321                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3322                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3323                                 {
3324                                         pixels[j+0] = 255;
3325                                         pixels[j+1] = 255;
3326                                         pixels[j+2] = 255;
3327                                         pixels[j+3] = basepixels[j+3];
3328                                 }
3329                                 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);
3330                                 Mem_Free(pixels);
3331                         }
3332                 }
3333                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3334 #ifndef USE_GLES2
3335                 //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]);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3337                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3339                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3340 #endif
3341         }
3342
3343         if (r_loaddds)
3344         {
3345                 mymiplevel = savemiplevel;
3346                 if (r_loadnormalmap)
3347                         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);
3348                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3349                 if (r_loadgloss)
3350                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3351                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3352                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3353                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3354         }
3355
3356         // _norm is the name used by tenebrae and has been adopted as standard
3357         if (r_loadnormalmap && skinframe->nmap == NULL)
3358         {
3359                 mymiplevel = savemiplevel;
3360                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3361                 {
3362                         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);
3363                         Mem_Free(pixels);
3364                         pixels = NULL;
3365                 }
3366                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3367                 {
3368                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3369                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3370                         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);
3371                         Mem_Free(pixels);
3372                         Mem_Free(bumppixels);
3373                 }
3374                 else if (r_shadow_bumpscale_basetexture.value > 0)
3375                 {
3376                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3377                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3378                         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);
3379                         Mem_Free(pixels);
3380                 }
3381 #ifndef USE_GLES2
3382                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3383                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3384 #endif
3385         }
3386
3387         // _luma is supported only for tenebrae compatibility
3388         // _glow is the preferred name
3389         mymiplevel = savemiplevel;
3390         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))))
3391         {
3392                 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);
3393 #ifndef USE_GLES2
3394                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3395                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3396 #endif
3397                 Mem_Free(pixels);pixels = NULL;
3398         }
3399
3400         mymiplevel = savemiplevel;
3401         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3402         {
3403                 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);
3404 #ifndef USE_GLES2
3405                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3406                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3407 #endif
3408                 Mem_Free(pixels);
3409                 pixels = NULL;
3410         }
3411
3412         mymiplevel = savemiplevel;
3413         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3414         {
3415                 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);
3416 #ifndef USE_GLES2
3417                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3418                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3419 #endif
3420                 Mem_Free(pixels);
3421                 pixels = NULL;
3422         }
3423
3424         mymiplevel = savemiplevel;
3425         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3426         {
3427                 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);
3428 #ifndef USE_GLES2
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3430                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3431 #endif
3432                 Mem_Free(pixels);
3433                 pixels = NULL;
3434         }
3435
3436         mymiplevel = savemiplevel;
3437         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3438         {
3439                 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);
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3442                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444                 Mem_Free(pixels);
3445                 pixels = NULL;
3446         }
3447
3448         if (basepixels)
3449                 Mem_Free(basepixels);
3450
3451         return skinframe;
3452 }
3453
3454 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3455 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3456 {
3457         int i;
3458         skinframe_t *skinframe;
3459         char vabuf[1024];
3460
3461         if (cls.state == ca_dedicated)
3462                 return NULL;
3463
3464         // if already loaded just return it, otherwise make a new skinframe
3465         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3466         if (skinframe->base)
3467                 return skinframe;
3468         textureflags &= ~TEXF_FORCE_RELOAD;
3469
3470         skinframe->stain = NULL;
3471         skinframe->merged = NULL;
3472         skinframe->base = NULL;
3473         skinframe->pants = NULL;
3474         skinframe->shirt = NULL;
3475         skinframe->nmap = NULL;
3476         skinframe->gloss = NULL;
3477         skinframe->glow = NULL;
3478         skinframe->fog = NULL;
3479         skinframe->reflect = NULL;
3480         skinframe->hasalpha = false;
3481
3482         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3483         if (!skindata)
3484                 return NULL;
3485
3486         if (developer_loading.integer)
3487                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3488
3489         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3490         {
3491                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3492                 unsigned char *b = a + width * height * 4;
3493                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3494                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3495                 Mem_Free(a);
3496         }
3497         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3498         if (textureflags & TEXF_ALPHA)
3499         {
3500                 for (i = 3;i < width * height * 4;i += 4)
3501                 {
3502                         if (skindata[i] < 255)
3503                         {
3504                                 skinframe->hasalpha = true;
3505                                 break;
3506                         }
3507                 }
3508                 if (r_loadfog && skinframe->hasalpha)
3509                 {
3510                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3511                         memcpy(fogpixels, skindata, width * height * 4);
3512                         for (i = 0;i < width * height * 4;i += 4)
3513                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3514                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3515                         Mem_Free(fogpixels);
3516                 }
3517         }
3518
3519         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3520         //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]);
3521
3522         return skinframe;
3523 }
3524
3525 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3526 {
3527         int i;
3528         int featuresmask;
3529         skinframe_t *skinframe;
3530
3531         if (cls.state == ca_dedicated)
3532                 return NULL;
3533
3534         // if already loaded just return it, otherwise make a new skinframe
3535         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3536         if (skinframe->base)
3537                 return skinframe;
3538         //textureflags &= ~TEXF_FORCE_RELOAD;
3539
3540         skinframe->stain = NULL;
3541         skinframe->merged = NULL;
3542         skinframe->base = NULL;
3543         skinframe->pants = NULL;
3544         skinframe->shirt = NULL;
3545         skinframe->nmap = NULL;
3546         skinframe->gloss = NULL;
3547         skinframe->glow = NULL;
3548         skinframe->fog = NULL;
3549         skinframe->reflect = NULL;
3550         skinframe->hasalpha = false;
3551
3552         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3553         if (!skindata)
3554                 return NULL;
3555
3556         if (developer_loading.integer)
3557                 Con_Printf("loading quake skin \"%s\"\n", name);
3558
3559         // 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)
3560         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3561         memcpy(skinframe->qpixels, skindata, width*height);
3562         skinframe->qwidth = width;
3563         skinframe->qheight = height;
3564
3565         featuresmask = 0;
3566         for (i = 0;i < width * height;i++)
3567                 featuresmask |= palette_featureflags[skindata[i]];
3568
3569         skinframe->hasalpha = false;
3570         // fence textures
3571         if (name[0] == '{')
3572                 skinframe->hasalpha = true;
3573         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3574         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3575         skinframe->qgeneratemerged = true;
3576         skinframe->qgeneratebase = skinframe->qhascolormapping;
3577         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3578
3579         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3580         //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]);
3581
3582         return skinframe;
3583 }
3584
3585 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3586 {
3587         int width;
3588         int height;
3589         unsigned char *skindata;
3590         char vabuf[1024];
3591
3592         if (!skinframe->qpixels)
3593                 return;
3594
3595         if (!skinframe->qhascolormapping)
3596                 colormapped = false;
3597
3598         if (colormapped)
3599         {
3600                 if (!skinframe->qgeneratebase)
3601                         return;
3602         }
3603         else
3604         {
3605                 if (!skinframe->qgeneratemerged)
3606                         return;
3607         }
3608
3609         width = skinframe->qwidth;
3610         height = skinframe->qheight;
3611         skindata = skinframe->qpixels;
3612
3613         if (skinframe->qgeneratenmap)
3614         {
3615                 unsigned char *a, *b;
3616                 skinframe->qgeneratenmap = false;
3617                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3618                 b = a + width * height * 4;
3619                 // use either a custom palette or the quake palette
3620                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3621                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3622                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3623                 Mem_Free(a);
3624         }
3625
3626         if (skinframe->qgenerateglow)
3627         {
3628                 skinframe->qgenerateglow = false;
3629                 if (skinframe->hasalpha) // fence textures
3630                         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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3631                 else
3632                         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
3633         }
3634
3635         if (colormapped)
3636         {
3637                 skinframe->qgeneratebase = false;
3638                 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);
3639                 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);
3640                 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);
3641         }
3642         else
3643         {
3644                 skinframe->qgeneratemerged = false;
3645                 if (skinframe->hasalpha) // fence textures
3646                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3647                 else
3648                         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);
3649         }
3650
3651         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3652         {
3653                 Mem_Free(skinframe->qpixels);
3654                 skinframe->qpixels = NULL;
3655         }
3656 }
3657
3658 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)
3659 {
3660         int i;
3661         skinframe_t *skinframe;
3662         char vabuf[1024];
3663
3664         if (cls.state == ca_dedicated)
3665                 return NULL;
3666
3667         // if already loaded just return it, otherwise make a new skinframe
3668         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3669         if (skinframe->base)
3670                 return skinframe;
3671         textureflags &= ~TEXF_FORCE_RELOAD;
3672
3673         skinframe->stain = NULL;
3674         skinframe->merged = NULL;
3675         skinframe->base = NULL;
3676         skinframe->pants = NULL;
3677         skinframe->shirt = NULL;
3678         skinframe->nmap = NULL;
3679         skinframe->gloss = NULL;
3680         skinframe->glow = NULL;
3681         skinframe->fog = NULL;
3682         skinframe->reflect = NULL;
3683         skinframe->hasalpha = false;
3684
3685         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3686         if (!skindata)
3687                 return NULL;
3688
3689         if (developer_loading.integer)
3690                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3691
3692         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3693         if ((textureflags & TEXF_ALPHA) && alphapalette)
3694         {
3695                 for (i = 0;i < width * height;i++)
3696                 {
3697                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3698                         {
3699                                 skinframe->hasalpha = true;
3700                                 break;
3701                         }
3702                 }
3703                 if (r_loadfog && skinframe->hasalpha)
3704                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3705         }
3706
3707         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3708         //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]);
3709
3710         return skinframe;
3711 }
3712
3713 skinframe_t *R_SkinFrame_LoadMissing(void)
3714 {
3715         skinframe_t *skinframe;
3716
3717         if (cls.state == ca_dedicated)
3718                 return NULL;
3719
3720         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3721         skinframe->stain = NULL;
3722         skinframe->merged = NULL;
3723         skinframe->base = NULL;
3724         skinframe->pants = NULL;
3725         skinframe->shirt = NULL;
3726         skinframe->nmap = NULL;
3727         skinframe->gloss = NULL;
3728         skinframe->glow = NULL;
3729         skinframe->fog = NULL;
3730         skinframe->reflect = NULL;
3731         skinframe->hasalpha = false;
3732
3733         skinframe->avgcolor[0] = rand() / RAND_MAX;
3734         skinframe->avgcolor[1] = rand() / RAND_MAX;
3735         skinframe->avgcolor[2] = rand() / RAND_MAX;
3736         skinframe->avgcolor[3] = 1;
3737
3738         return skinframe;
3739 }
3740
3741 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3742 {
3743         int x, y;
3744         static unsigned char pix[16][16][4];
3745
3746         if (cls.state == ca_dedicated)
3747                 return NULL;
3748
3749         // this makes a light grey/dark grey checkerboard texture
3750         if (!pix[0][0][3])
3751         {
3752                 for (y = 0; y < 16; y++)
3753                 {
3754                         for (x = 0; x < 16; x++)
3755                         {
3756                                 if ((y < 8) ^ (x < 8))
3757                                 {
3758                                         pix[y][x][0] = 128;
3759                                         pix[y][x][1] = 128;
3760                                         pix[y][x][2] = 128;
3761                                         pix[y][x][3] = 255;
3762                                 }
3763                                 else
3764                                 {
3765                                         pix[y][x][0] = 64;
3766                                         pix[y][x][1] = 64;
3767                                         pix[y][x][2] = 64;
3768                                         pix[y][x][3] = 255;
3769                                 }
3770                         }
3771                 }
3772         }
3773
3774         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3775 }
3776
3777 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3778 {
3779         skinframe_t *skinframe;
3780         if (cls.state == ca_dedicated)
3781                 return NULL;
3782         // if already loaded just return it, otherwise make a new skinframe
3783         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3784         if (skinframe->base)
3785                 return skinframe;
3786         textureflags &= ~TEXF_FORCE_RELOAD;
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 = (textureflags & TEXF_ALPHA) != 0;
3798         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3799         if (!tex)
3800                 return NULL;
3801         if (developer_loading.integer)
3802                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3803         skinframe->base = skinframe->merged = tex;
3804         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3805         return skinframe;
3806 }
3807
3808 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3809 typedef struct suffixinfo_s
3810 {
3811         const char *suffix;
3812         qboolean flipx, flipy, flipdiagonal;
3813 }
3814 suffixinfo_t;
3815 static suffixinfo_t suffix[3][6] =
3816 {
3817         {
3818                 {"px",   false, false, false},
3819                 {"nx",   false, false, false},
3820                 {"py",   false, false, false},
3821                 {"ny",   false, false, false},
3822                 {"pz",   false, false, false},
3823                 {"nz",   false, false, false}
3824         },
3825         {
3826                 {"posx", false, false, false},
3827                 {"negx", false, false, false},
3828                 {"posy", false, false, false},
3829                 {"negy", false, false, false},
3830                 {"posz", false, false, false},
3831                 {"negz", false, false, false}
3832         },
3833         {
3834                 {"rt",    true, false,  true},
3835                 {"lf",   false,  true,  true},
3836                 {"ft",    true,  true, false},
3837                 {"bk",   false, false, false},
3838                 {"up",    true, false,  true},
3839                 {"dn",    true, false,  true}
3840         }
3841 };
3842
3843 static int componentorder[4] = {0, 1, 2, 3};
3844
3845 static rtexture_t *R_LoadCubemap(const char *basename)
3846 {
3847         int i, j, cubemapsize;
3848         unsigned char *cubemappixels, *image_buffer;
3849         rtexture_t *cubemaptexture;
3850         char name[256];
3851         // must start 0 so the first loadimagepixels has no requested width/height
3852         cubemapsize = 0;
3853         cubemappixels = NULL;
3854         cubemaptexture = NULL;
3855         // keep trying different suffix groups (posx, px, rt) until one loads
3856         for (j = 0;j < 3 && !cubemappixels;j++)
3857         {
3858                 // load the 6 images in the suffix group
3859                 for (i = 0;i < 6;i++)
3860                 {
3861                         // generate an image name based on the base and and suffix
3862                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3863                         // load it
3864                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3865                         {
3866                                 // an image loaded, make sure width and height are equal
3867                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3868                                 {
3869                                         // if this is the first image to load successfully, allocate the cubemap memory
3870                                         if (!cubemappixels && image_width >= 1)
3871                                         {
3872                                                 cubemapsize = image_width;
3873                                                 // note this clears to black, so unavailable sides are black
3874                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3875                                         }
3876                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3877                                         if (cubemappixels)
3878                                                 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);
3879                                 }
3880                                 else
3881                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3882                                 // free the image
3883                                 Mem_Free(image_buffer);
3884                         }
3885                 }
3886         }
3887         // if a cubemap loaded, upload it
3888         if (cubemappixels)
3889         {
3890                 if (developer_loading.integer)
3891                         Con_Printf("loading cubemap \"%s\"\n", basename);
3892
3893                 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);
3894                 Mem_Free(cubemappixels);
3895         }
3896         else
3897         {
3898                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3899                 if (developer_loading.integer)
3900                 {
3901                         Con_Printf("(tried tried images ");
3902                         for (j = 0;j < 3;j++)
3903                                 for (i = 0;i < 6;i++)
3904                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3905                         Con_Print(" and was unable to find any of them).\n");
3906                 }
3907         }
3908         return cubemaptexture;
3909 }
3910
3911 rtexture_t *R_GetCubemap(const char *basename)
3912 {
3913         int i;
3914         for (i = 0;i < r_texture_numcubemaps;i++)
3915                 if (r_texture_cubemaps[i] != NULL)
3916                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3917                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3918         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3919                 return r_texture_whitecube;
3920         r_texture_numcubemaps++;
3921         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3922         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3923         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3924         return r_texture_cubemaps[i]->texture;
3925 }
3926
3927 static void R_Main_FreeViewCache(void)
3928 {
3929         if (r_refdef.viewcache.entityvisible)
3930                 Mem_Free(r_refdef.viewcache.entityvisible);
3931         if (r_refdef.viewcache.world_pvsbits)
3932                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933         if (r_refdef.viewcache.world_leafvisible)
3934                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935         if (r_refdef.viewcache.world_surfacevisible)
3936                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3938 }
3939
3940 static void R_Main_ResizeViewCache(void)
3941 {
3942         int numentities = r_refdef.scene.numentities;
3943         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947         if (r_refdef.viewcache.maxentities < numentities)
3948         {
3949                 r_refdef.viewcache.maxentities = numentities;
3950                 if (r_refdef.viewcache.entityvisible)
3951                         Mem_Free(r_refdef.viewcache.entityvisible);
3952                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3953         }
3954         if (r_refdef.viewcache.world_numclusters != numclusters)
3955         {
3956                 r_refdef.viewcache.world_numclusters = numclusters;
3957                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958                 if (r_refdef.viewcache.world_pvsbits)
3959                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3960                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3961         }
3962         if (r_refdef.viewcache.world_numleafs != numleafs)
3963         {
3964                 r_refdef.viewcache.world_numleafs = numleafs;
3965                 if (r_refdef.viewcache.world_leafvisible)
3966                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3967                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3968         }
3969         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3970         {
3971                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972                 if (r_refdef.viewcache.world_surfacevisible)
3973                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3975         }
3976 }
3977
3978 extern rtexture_t *loadingscreentexture;
3979 static void gl_main_start(void)
3980 {
3981         loadingscreentexture = NULL;
3982         r_texture_blanknormalmap = NULL;
3983         r_texture_white = NULL;
3984         r_texture_grey128 = NULL;
3985         r_texture_black = NULL;
3986         r_texture_whitecube = NULL;
3987         r_texture_normalizationcube = NULL;
3988         r_texture_fogattenuation = NULL;
3989         r_texture_fogheighttexture = NULL;
3990         r_texture_gammaramps = NULL;
3991         r_texture_numcubemaps = 0;
3992         r_uniformbufferalignment = 32;
3993
3994         r_loaddds = r_texture_dds_load.integer != 0;
3995         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3996
3997         switch(vid.renderpath)
3998         {
3999         case RENDERPATH_GL20:
4000         case RENDERPATH_D3D9:
4001         case RENDERPATH_D3D10:
4002         case RENDERPATH_D3D11:
4003         case RENDERPATH_SOFT:
4004         case RENDERPATH_GLES2:
4005                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006                 Cvar_SetValueQuick(&gl_combine, 1);
4007                 Cvar_SetValueQuick(&r_glsl, 1);
4008                 r_loadnormalmap = true;
4009                 r_loadgloss = true;
4010                 r_loadfog = false;
4011 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4012                 if (vid.support.arb_uniform_buffer_object)
4013                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4014 #endif
4015                         break;
4016         case RENDERPATH_GL13:
4017         case RENDERPATH_GLES1:
4018                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4019                 Cvar_SetValueQuick(&gl_combine, 1);
4020                 Cvar_SetValueQuick(&r_glsl, 0);
4021                 r_loadnormalmap = false;
4022                 r_loadgloss = false;
4023                 r_loadfog = true;
4024                 break;
4025         case RENDERPATH_GL11:
4026                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4027                 Cvar_SetValueQuick(&gl_combine, 0);
4028                 Cvar_SetValueQuick(&r_glsl, 0);
4029                 r_loadnormalmap = false;
4030                 r_loadgloss = false;
4031                 r_loadfog = true;
4032                 break;
4033         }
4034
4035         R_AnimCache_Free();
4036         R_FrameData_Reset();
4037         R_BufferData_Reset();
4038
4039         r_numqueries = 0;
4040         r_maxqueries = 0;
4041         memset(r_queries, 0, sizeof(r_queries));
4042
4043         r_qwskincache = NULL;
4044         r_qwskincache_size = 0;
4045
4046         // due to caching of texture_t references, the collision cache must be reset
4047         Collision_Cache_Reset(true);
4048
4049         // set up r_skinframe loading system for textures
4050         memset(&r_skinframe, 0, sizeof(r_skinframe));
4051         r_skinframe.loadsequence = 1;
4052         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4053
4054         r_main_texturepool = R_AllocTexturePool();
4055         R_BuildBlankTextures();
4056         R_BuildNoTexture();
4057         if (vid.support.arb_texture_cube_map)
4058         {
4059                 R_BuildWhiteCube();
4060                 R_BuildNormalizationCube();
4061         }
4062         r_texture_fogattenuation = NULL;
4063         r_texture_fogheighttexture = NULL;
4064         r_texture_gammaramps = NULL;
4065         //r_texture_fogintensity = NULL;
4066         memset(&r_fb, 0, sizeof(r_fb));
4067         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4068         r_glsl_permutation = NULL;
4069         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4070         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4071 #ifdef SUPPORTD3D
4072         r_hlsl_permutation = NULL;
4073         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4074         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4075 #endif
4076         memset(&r_svbsp, 0, sizeof (r_svbsp));
4077
4078         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4079         r_texture_numcubemaps = 0;
4080
4081         r_refdef.fogmasktable_density = 0;
4082
4083 #ifdef __ANDROID__
4084         // For Steelstorm Android
4085         // FIXME CACHE the program and reload
4086         // FIXME see possible combinations for SS:BR android
4087         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4088         R_SetupShader_SetPermutationGLSL(0, 12);
4089         R_SetupShader_SetPermutationGLSL(0, 13);
4090         R_SetupShader_SetPermutationGLSL(0, 8388621);
4091         R_SetupShader_SetPermutationGLSL(3, 0);
4092         R_SetupShader_SetPermutationGLSL(3, 2048);
4093         R_SetupShader_SetPermutationGLSL(5, 0);
4094         R_SetupShader_SetPermutationGLSL(5, 2);
4095         R_SetupShader_SetPermutationGLSL(5, 2048);
4096         R_SetupShader_SetPermutationGLSL(5, 8388608);
4097         R_SetupShader_SetPermutationGLSL(11, 1);
4098         R_SetupShader_SetPermutationGLSL(11, 2049);
4099         R_SetupShader_SetPermutationGLSL(11, 8193);
4100         R_SetupShader_SetPermutationGLSL(11, 10241);
4101         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4102 #endif
4103 }
4104
4105 static void gl_main_shutdown(void)
4106 {
4107         R_RenderTarget_FreeUnused(true);
4108         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4109         R_AnimCache_Free();
4110         R_FrameData_Reset();
4111         R_BufferData_Reset();
4112
4113         R_Main_FreeViewCache();
4114
4115         switch(vid.renderpath)
4116         {
4117         case RENDERPATH_GL11:
4118         case RENDERPATH_GL13:
4119         case RENDERPATH_GL20:
4120         case RENDERPATH_GLES1:
4121         case RENDERPATH_GLES2:
4122 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4123                 if (r_maxqueries)
4124                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4125 #endif
4126                 break;
4127         case RENDERPATH_D3D9:
4128                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4129                 break;
4130         case RENDERPATH_D3D10:
4131                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4132                 break;
4133         case RENDERPATH_D3D11:
4134                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4135                 break;
4136         case RENDERPATH_SOFT:
4137                 break;
4138         }
4139
4140         r_numqueries = 0;
4141         r_maxqueries = 0;
4142         memset(r_queries, 0, sizeof(r_queries));
4143
4144         r_qwskincache = NULL;
4145         r_qwskincache_size = 0;
4146
4147         // clear out the r_skinframe state
4148         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4149         memset(&r_skinframe, 0, sizeof(r_skinframe));
4150
4151         if (r_svbsp.nodes)
4152                 Mem_Free(r_svbsp.nodes);
4153         memset(&r_svbsp, 0, sizeof (r_svbsp));
4154         R_FreeTexturePool(&r_main_texturepool);
4155         loadingscreentexture = NULL;
4156         r_texture_blanknormalmap = NULL;
4157         r_texture_white = NULL;
4158         r_texture_grey128 = NULL;
4159         r_texture_black = NULL;
4160         r_texture_whitecube = NULL;
4161         r_texture_normalizationcube = NULL;
4162         r_texture_fogattenuation = NULL;
4163         r_texture_fogheighttexture = NULL;
4164         r_texture_gammaramps = NULL;
4165         r_texture_numcubemaps = 0;
4166         //r_texture_fogintensity = NULL;
4167         memset(&r_fb, 0, sizeof(r_fb));
4168         R_GLSL_Restart_f();
4169
4170         r_glsl_permutation = NULL;
4171         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4172         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4173 #ifdef SUPPORTD3D
4174         r_hlsl_permutation = NULL;
4175         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4176         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4177 #endif
4178 }
4179
4180 static void gl_main_newmap(void)
4181 {
4182         // FIXME: move this code to client
4183         char *entities, entname[MAX_QPATH];
4184         if (r_qwskincache)
4185                 Mem_Free(r_qwskincache);
4186         r_qwskincache = NULL;
4187         r_qwskincache_size = 0;
4188         if (cl.worldmodel)
4189         {
4190                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4191                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4192                 {
4193                         CL_ParseEntityLump(entities);
4194                         Mem_Free(entities);
4195                         return;
4196                 }
4197                 if (cl.worldmodel->brush.entities)
4198                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4199         }
4200         R_Main_FreeViewCache();
4201
4202         R_FrameData_Reset();
4203         R_BufferData_Reset();
4204 }
4205
4206 void GL_Main_Init(void)
4207 {
4208         int i;
4209         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4210         R_InitShaderModeInfo();
4211
4212         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4213         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4214         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4215         if (gamemode == GAME_NEHAHRA)
4216         {
4217                 Cvar_RegisterVariable (&gl_fogenable);
4218                 Cvar_RegisterVariable (&gl_fogdensity);
4219                 Cvar_RegisterVariable (&gl_fogred);
4220                 Cvar_RegisterVariable (&gl_foggreen);
4221                 Cvar_RegisterVariable (&gl_fogblue);
4222                 Cvar_RegisterVariable (&gl_fogstart);
4223                 Cvar_RegisterVariable (&gl_fogend);
4224                 Cvar_RegisterVariable (&gl_skyclip);
4225         }
4226         Cvar_RegisterVariable(&r_motionblur);
4227         Cvar_RegisterVariable(&r_damageblur);
4228         Cvar_RegisterVariable(&r_motionblur_averaging);
4229         Cvar_RegisterVariable(&r_motionblur_randomize);
4230         Cvar_RegisterVariable(&r_motionblur_minblur);
4231         Cvar_RegisterVariable(&r_motionblur_maxblur);
4232         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4233         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4234         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4235         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4236         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4237         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4238         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4239         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4240         Cvar_RegisterVariable(&r_equalize_entities_by);
4241         Cvar_RegisterVariable(&r_equalize_entities_to);
4242         Cvar_RegisterVariable(&r_depthfirst);
4243         Cvar_RegisterVariable(&r_useinfinitefarclip);
4244         Cvar_RegisterVariable(&r_farclip_base);
4245         Cvar_RegisterVariable(&r_farclip_world);
4246         Cvar_RegisterVariable(&r_nearclip);
4247         Cvar_RegisterVariable(&r_deformvertexes);
4248         Cvar_RegisterVariable(&r_transparent);
4249         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4250         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4251         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4252         Cvar_RegisterVariable(&r_showoverdraw);
4253         Cvar_RegisterVariable(&r_showbboxes);
4254         Cvar_RegisterVariable(&r_showbboxes_client);
4255         Cvar_RegisterVariable(&r_showsurfaces);
4256         Cvar_RegisterVariable(&r_showtris);
4257         Cvar_RegisterVariable(&r_shownormals);
4258         Cvar_RegisterVariable(&r_showlighting);
4259         Cvar_RegisterVariable(&r_showshadowvolumes);
4260         Cvar_RegisterVariable(&r_showcollisionbrushes);
4261         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4262         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4263         Cvar_RegisterVariable(&r_showdisabledepthtest);
4264         Cvar_RegisterVariable(&r_showspriteedges);
4265         Cvar_RegisterVariable(&r_showparticleedges);
4266         Cvar_RegisterVariable(&r_drawportals);
4267         Cvar_RegisterVariable(&r_drawentities);
4268         Cvar_RegisterVariable(&r_draw2d);
4269         Cvar_RegisterVariable(&r_drawworld);
4270         Cvar_RegisterVariable(&r_cullentities_trace);
4271         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4272         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4273         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4274         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4275         Cvar_RegisterVariable(&r_cullentities_trace_expand);
4276         Cvar_RegisterVariable(&r_cullentities_trace_pad);
4277         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4278         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4279         Cvar_RegisterVariable(&r_sortentities);
4280         Cvar_RegisterVariable(&r_drawviewmodel);
4281         Cvar_RegisterVariable(&r_drawexteriormodel);
4282         Cvar_RegisterVariable(&r_speeds);
4283         Cvar_RegisterVariable(&r_fullbrights);
4284         Cvar_RegisterVariable(&r_wateralpha);
4285         Cvar_RegisterVariable(&r_dynamic);
4286         Cvar_RegisterVariable(&r_fakelight);
4287         Cvar_RegisterVariable(&r_fakelight_intensity);
4288         Cvar_RegisterVariable(&r_fullbright_directed);
4289         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4290         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4291         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4292         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4293         Cvar_RegisterVariable(&r_fullbright);
4294         Cvar_RegisterVariable(&r_shadows);
4295         Cvar_RegisterVariable(&r_shadows_darken);
4296         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4297         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4298         Cvar_RegisterVariable(&r_shadows_throwdistance);
4299         Cvar_RegisterVariable(&r_shadows_throwdirection);
4300         Cvar_RegisterVariable(&r_shadows_focus);
4301         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4302         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4303         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4304         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4305         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4306         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4307         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4308         Cvar_RegisterVariable(&r_fog_exp2);
4309         Cvar_RegisterVariable(&r_fog_clear);
4310         Cvar_RegisterVariable(&r_drawfog);
4311         Cvar_RegisterVariable(&r_transparentdepthmasking);
4312         Cvar_RegisterVariable(&r_transparent_sortmindist);
4313         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4314         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4315         Cvar_RegisterVariable(&r_texture_dds_load);
4316         Cvar_RegisterVariable(&r_texture_dds_save);
4317         Cvar_RegisterVariable(&r_textureunits);
4318         Cvar_RegisterVariable(&gl_combine);
4319         Cvar_RegisterVariable(&r_usedepthtextures);
4320         Cvar_RegisterVariable(&r_viewfbo);
4321         Cvar_RegisterVariable(&r_rendertarget_debug);
4322         Cvar_RegisterVariable(&r_viewscale);
4323         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4324         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4325         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4326         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4327         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4328         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4329         Cvar_RegisterVariable(&r_glsl);
4330         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4331         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4332         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4333         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4334         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4335         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4336         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4337         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4338         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4339         Cvar_RegisterVariable(&r_glsl_postprocess);
4340         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4341         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4342         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4343         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4344         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4345         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4346         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4347         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4348         Cvar_RegisterVariable(&r_celshading);
4349         Cvar_RegisterVariable(&r_celoutlines);
4350
4351         Cvar_RegisterVariable(&r_water);
4352         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4353         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4354         Cvar_RegisterVariable(&r_water_clippingplanebias);
4355         Cvar_RegisterVariable(&r_water_refractdistort);
4356         Cvar_RegisterVariable(&r_water_reflectdistort);
4357         Cvar_RegisterVariable(&r_water_scissormode);
4358         Cvar_RegisterVariable(&r_water_lowquality);
4359         Cvar_RegisterVariable(&r_water_hideplayer);
4360
4361         Cvar_RegisterVariable(&r_lerpsprites);
4362         Cvar_RegisterVariable(&r_lerpmodels);
4363         Cvar_RegisterVariable(&r_lerplightstyles);
4364         Cvar_RegisterVariable(&r_waterscroll);
4365         Cvar_RegisterVariable(&r_bloom);
4366         Cvar_RegisterVariable(&r_bloom_colorscale);
4367         Cvar_RegisterVariable(&r_bloom_brighten);
4368         Cvar_RegisterVariable(&r_bloom_blur);
4369         Cvar_RegisterVariable(&r_bloom_resolution);
4370         Cvar_RegisterVariable(&r_bloom_colorexponent);
4371         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4372         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4373         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4374         Cvar_RegisterVariable(&r_hdr_glowintensity);
4375         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4376         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4377         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4378         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4379         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4380         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4381         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4382         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4383         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4384         Cvar_RegisterVariable(&developer_texturelogging);
4385         Cvar_RegisterVariable(&gl_lightmaps);
4386         Cvar_RegisterVariable(&r_test);
4387         Cvar_RegisterVariable(&r_batch_multidraw);
4388         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4389         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4390         Cvar_RegisterVariable(&r_glsl_skeletal);
4391         Cvar_RegisterVariable(&r_glsl_saturation);
4392         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4393         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4394         Cvar_RegisterVariable(&r_framedatasize);
4395         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4396                 Cvar_RegisterVariable(&r_buffermegs[i]);
4397         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4398         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4399                 Cvar_SetValue("r_fullbrights", 0);
4400 #ifdef DP_MOBILETOUCH
4401         // GLES devices have terrible depth precision in general, so...
4402         Cvar_SetValueQuick(&r_nearclip, 4);
4403         Cvar_SetValueQuick(&r_farclip_base, 4096);
4404         Cvar_SetValueQuick(&r_farclip_world, 0);
4405         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4406 #endif
4407         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4408 }
4409
4410 void Render_Init(void)
4411 {
4412         gl_backend_init();
4413         R_Textures_Init();
4414         GL_Main_Init();
4415         Font_Init();
4416         GL_Draw_Init();
4417         R_Shadow_Init();
4418         R_Sky_Init();
4419         GL_Surf_Init();
4420         Sbar_Init();
4421         R_Particles_Init();
4422         R_Explosion_Init();
4423         R_LightningBeams_Init();
4424         Mod_RenderInit();
4425 }
4426
4427 /*
4428 ===============
4429 GL_Init
4430 ===============
4431 */
4432 #ifndef USE_GLES2
4433 extern char *ENGINE_EXTENSIONS;
4434 void GL_Init (void)
4435 {
4436         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4437         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4438         gl_version = (const char *)qglGetString(GL_VERSION);
4439         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4440
4441         if (!gl_extensions)
4442                 gl_extensions = "";
4443         if (!gl_platformextensions)
4444                 gl_platformextensions = "";
4445
4446         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4447         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4448         Con_Printf("GL_VERSION: %s\n", gl_version);
4449         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4450         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4451
4452         VID_CheckExtensions();
4453
4454         // LordHavoc: report supported extensions
4455 #ifdef CONFIG_MENU
4456         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4457 #else
4458         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4459 #endif
4460
4461         // clear to black (loading plaque will be seen over this)
4462         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4463 }
4464 #endif
4465
4466 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4467 {
4468         int i;
4469         mplane_t *p;
4470         if (r_trippy.integer)
4471                 return false;
4472         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4473         {
4474                 p = r_refdef.view.frustum + i;
4475                 switch(p->signbits)
4476                 {
4477                 default:
4478                 case 0:
4479                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 1:
4483                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 2:
4487                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 3:
4491                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 4:
4495                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 5:
4499                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 6:
4503                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 7:
4507                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 }
4511         }
4512         return false;
4513 }
4514
4515 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4516 {
4517         int i;
4518         const mplane_t *p;
4519         if (r_trippy.integer)
4520                 return false;
4521         for (i = 0;i < numplanes;i++)
4522         {
4523                 p = planes + i;
4524                 switch(p->signbits)
4525                 {
4526                 default:
4527                 case 0:
4528                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 case 1:
4532                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4533                                 return true;
4534                         break;
4535                 case 2:
4536                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4537                                 return true;
4538                         break;
4539                 case 3:
4540                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4541                                 return true;
4542                         break;
4543                 case 4:
4544                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4545                                 return true;
4546                         break;
4547                 case 5:
4548                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4549                                 return true;
4550                         break;
4551                 case 6:
4552                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4553                                 return true;
4554                         break;
4555                 case 7:
4556                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4557                                 return true;
4558                         break;
4559                 }
4560         }
4561         return false;
4562 }
4563
4564 //==================================================================================
4565
4566 // LordHavoc: this stores temporary data used within the same frame
4567
4568 typedef struct r_framedata_mem_s
4569 {
4570         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4571         size_t size; // how much usable space
4572         size_t current; // how much space in use
4573         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4574         size_t wantedsize; // how much space was allocated
4575         unsigned char *data; // start of real data (16byte aligned)
4576 }
4577 r_framedata_mem_t;
4578
4579 static r_framedata_mem_t *r_framedata_mem;
4580
4581 void R_FrameData_Reset(void)
4582 {
4583         while (r_framedata_mem)
4584         {
4585                 r_framedata_mem_t *next = r_framedata_mem->purge;
4586                 Mem_Free(r_framedata_mem);
4587                 r_framedata_mem = next;
4588         }
4589 }
4590
4591 static void R_FrameData_Resize(qboolean mustgrow)
4592 {
4593         size_t wantedsize;
4594         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4595         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4596         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4597         {
4598                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4599                 newmem->wantedsize = wantedsize;
4600                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4601                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4602                 newmem->current = 0;
4603                 newmem->mark = 0;
4604                 newmem->purge = r_framedata_mem;
4605                 r_framedata_mem = newmem;
4606         }
4607 }
4608
4609 void R_FrameData_NewFrame(void)
4610 {
4611         R_FrameData_Resize(false);
4612         if (!r_framedata_mem)
4613                 return;
4614         // if we ran out of space on the last frame, free the old memory now
4615         while (r_framedata_mem->purge)
4616         {
4617                 // repeatedly remove the second item in the list, leaving only head
4618                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4619                 Mem_Free(r_framedata_mem->purge);
4620                 r_framedata_mem->purge = next;
4621         }
4622         // reset the current mem pointer
4623         r_framedata_mem->current = 0;
4624         r_framedata_mem->mark = 0;
4625 }
4626
4627 void *R_FrameData_Alloc(size_t size)
4628 {
4629         void *data;
4630         float newvalue;
4631
4632         // align to 16 byte boundary - the data pointer is already aligned, so we
4633         // only need to ensure the size of every allocation is also aligned
4634         size = (size + 15) & ~15;
4635
4636         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4637         {
4638                 // emergency - we ran out of space, allocate more memory
4639                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4640                 newvalue = r_framedatasize.value * 2.0f;
4641                 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4642                 if (sizeof(size_t) >= 8)
4643                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4644                 else
4645                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4646                 // this might not be a growing it, but we'll allocate another buffer every time
4647                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4648                 R_FrameData_Resize(true);
4649         }
4650
4651         data = r_framedata_mem->data + r_framedata_mem->current;
4652         r_framedata_mem->current += size;
4653
4654         // count the usage for stats
4655         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4656         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4657
4658         return (void *)data;
4659 }
4660
4661 void *R_FrameData_Store(size_t size, void *data)
4662 {
4663         void *d = R_FrameData_Alloc(size);
4664         if (d && data)
4665                 memcpy(d, data, size);
4666         return d;
4667 }
4668
4669 void R_FrameData_SetMark(void)
4670 {
4671         if (!r_framedata_mem)
4672                 return;
4673         r_framedata_mem->mark = r_framedata_mem->current;
4674 }
4675
4676 void R_FrameData_ReturnToMark(void)
4677 {
4678         if (!r_framedata_mem)
4679                 return;
4680         r_framedata_mem->current = r_framedata_mem->mark;
4681 }
4682
4683 //==================================================================================
4684
4685 // avoid reusing the same buffer objects on consecutive frames
4686 #define R_BUFFERDATA_CYCLE 3
4687
4688 typedef struct r_bufferdata_buffer_s
4689 {
4690         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4691         size_t size; // how much usable space
4692         size_t current; // how much space in use
4693         r_meshbuffer_t *buffer; // the buffer itself
4694 }
4695 r_bufferdata_buffer_t;
4696
4697 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4698 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4699
4700 /// frees all dynamic buffers
4701 void R_BufferData_Reset(void)
4702 {
4703         int cycle, type;
4704         r_bufferdata_buffer_t **p, *mem;
4705         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4706         {
4707                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4708                 {
4709                         // free all buffers
4710                         p = &r_bufferdata_buffer[cycle][type];
4711                         while (*p)
4712                         {
4713                                 mem = *p;
4714                                 *p = (*p)->purge;
4715                                 if (mem->buffer)
4716                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4717                                 Mem_Free(mem);
4718                         }
4719                 }
4720         }
4721 }
4722
4723 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4724 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4725 {
4726         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4727         size_t size;
4728         float newvalue = r_buffermegs[type].value;
4729
4730         // increase the cvar if we have to (but only if we already have a mem)
4731         if (mustgrow && mem)
4732                 newvalue *= 2.0f;
4733         newvalue = bound(0.25f, newvalue, 256.0f);
4734         while (newvalue * 1024*1024 < minsize)
4735                 newvalue *= 2.0f;
4736
4737         // clamp the cvar to valid range
4738         newvalue = bound(0.25f, newvalue, 256.0f);
4739         if (r_buffermegs[type].value != newvalue)
4740                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4741
4742         // calculate size in bytes
4743         size = (size_t)(newvalue * 1024*1024);
4744         size = bound(131072, size, 256*1024*1024);
4745
4746         // allocate a new buffer if the size is different (purge old one later)
4747         // or if we were told we must grow the buffer
4748         if (!mem || mem->size != size || mustgrow)
4749         {
4750                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4751                 mem->size = size;
4752                 mem->current = 0;
4753                 if (type == R_BUFFERDATA_VERTEX)
4754                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4755                 else if (type == R_BUFFERDATA_INDEX16)
4756                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4757                 else if (type == R_BUFFERDATA_INDEX32)
4758                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4759                 else if (type == R_BUFFERDATA_UNIFORM)
4760                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4761                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4762                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4763         }
4764 }
4765
4766 void R_BufferData_NewFrame(void)
4767 {
4768         int type;
4769         r_bufferdata_buffer_t **p, *mem;
4770         // cycle to the next frame's buffers
4771         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4772         // if we ran out of space on the last time we used these buffers, free the old memory now
4773         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4774         {
4775                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4776                 {
4777                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4778                         // free all but the head buffer, this is how we recycle obsolete
4779                         // buffers after they are no longer in use
4780                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4781                         while (*p)
4782                         {
4783                                 mem = *p;
4784                                 *p = (*p)->purge;
4785                                 if (mem->buffer)
4786                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4787                                 Mem_Free(mem);
4788                         }
4789                         // reset the current offset
4790                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4791                 }
4792         }
4793 }
4794
4795 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4796 {
4797         r_bufferdata_buffer_t *mem;
4798         int offset = 0;
4799         int padsize;
4800
4801         *returnbufferoffset = 0;
4802
4803         // align size to a byte boundary appropriate for the buffer type, this
4804         // makes all allocations have aligned start offsets
4805         if (type == R_BUFFERDATA_UNIFORM)
4806                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4807         else
4808                 padsize = (datasize + 15) & ~15;
4809
4810         // if we ran out of space in this buffer we must allocate a new one
4811         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4812                 R_BufferData_Resize(type, true, padsize);
4813
4814         // if the resize did not give us enough memory, fail
4815         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4816                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4817
4818         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4819         offset = (int)mem->current;
4820         mem->current += padsize;
4821
4822         // upload the data to the buffer at the chosen offset
4823         if (offset == 0)
4824                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4825         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4826
4827         // count the usage for stats
4828         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4829         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4830
4831         // return the buffer offset
4832         *returnbufferoffset = offset;
4833
4834         return mem->buffer;
4835 }
4836
4837 //==================================================================================
4838
4839 // LordHavoc: animcache originally written by Echon, rewritten since then
4840
4841 /**
4842  * Animation cache prevents re-generating mesh data for an animated model
4843  * multiple times in one frame for lighting, shadowing, reflections, etc.
4844  */
4845
4846 void R_AnimCache_Free(void)
4847 {
4848 }
4849
4850 void R_AnimCache_ClearCache(void)
4851 {
4852         int i;
4853         entity_render_t *ent;
4854
4855         for (i = 0;i < r_refdef.scene.numentities;i++)
4856         {
4857                 ent = r_refdef.scene.entities[i];
4858                 ent->animcache_vertex3f = NULL;
4859                 ent->animcache_vertex3f_vertexbuffer = NULL;
4860                 ent->animcache_vertex3f_bufferoffset = 0;
4861                 ent->animcache_normal3f = NULL;
4862                 ent->animcache_normal3f_vertexbuffer = NULL;
4863                 ent->animcache_normal3f_bufferoffset = 0;
4864                 ent->animcache_svector3f = NULL;
4865                 ent->animcache_svector3f_vertexbuffer = NULL;
4866                 ent->animcache_svector3f_bufferoffset = 0;
4867                 ent->animcache_tvector3f = NULL;
4868                 ent->animcache_tvector3f_vertexbuffer = NULL;
4869                 ent->animcache_tvector3f_bufferoffset = 0;
4870                 ent->animcache_vertexmesh = NULL;
4871                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4872                 ent->animcache_vertexmesh_bufferoffset = 0;
4873                 ent->animcache_skeletaltransform3x4 = NULL;
4874                 ent->animcache_skeletaltransform3x4buffer = NULL;
4875                 ent->animcache_skeletaltransform3x4offset = 0;
4876                 ent->animcache_skeletaltransform3x4size = 0;
4877         }
4878 }
4879
4880 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4881 {
4882         int i;
4883
4884         // check if we need the meshbuffers
4885         if (!vid.useinterleavedarrays)
4886                 return;
4887
4888         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4889                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4890         // TODO: upload vertexbuffer?
4891         if (ent->animcache_vertexmesh)
4892         {
4893                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4894                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4895                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4896                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4897                 for (i = 0;i < numvertices;i++)
4898                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4899                 if (ent->animcache_svector3f)
4900                         for (i = 0;i < numvertices;i++)
4901                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4902                 if (ent->animcache_tvector3f)
4903                         for (i = 0;i < numvertices;i++)
4904                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4905                 if (ent->animcache_normal3f)
4906                         for (i = 0;i < numvertices;i++)
4907                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4908         }
4909 }
4910
4911 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4912 {
4913         dp_model_t *model = ent->model;
4914         int numvertices;
4915
4916         // see if this ent is worth caching
4917         if (!model || !model->Draw || !model->AnimateVertices)
4918                 return false;
4919         // nothing to cache if it contains no animations and has no skeleton
4920         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4921                 return false;
4922         // see if it is already cached for gpuskeletal
4923         if (ent->animcache_skeletaltransform3x4)
4924                 return false;
4925         // see if it is already cached as a mesh
4926         if (ent->animcache_vertex3f)
4927         {
4928                 // check if we need to add normals or tangents
4929                 if (ent->animcache_normal3f)
4930                         wantnormals = false;
4931                 if (ent->animcache_svector3f)
4932                         wanttangents = false;
4933                 if (!wantnormals && !wanttangents)
4934                         return false;
4935         }
4936
4937         // check which kind of cache we need to generate
4938         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4939         {
4940                 // cache the skeleton so the vertex shader can use it
4941                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4942                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4943                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4944                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4945                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4946                 // note: this can fail if the buffer is at the grow limit
4947                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4948                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4949         }
4950         else if (ent->animcache_vertex3f)
4951         {
4952                 // mesh was already cached but we may need to add normals/tangents
4953                 // (this only happens with multiple views, reflections, cameras, etc)
4954                 if (wantnormals || wanttangents)
4955                 {
4956                         numvertices = model->surfmesh.num_vertices;
4957                         if (wantnormals)
4958                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4959                         if (wanttangents)
4960                         {
4961                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4962                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4963                         }
4964                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4965                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4966                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4967                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4968                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4969                 }
4970         }
4971         else
4972         {
4973                 // generate mesh cache
4974                 numvertices = model->surfmesh.num_vertices;
4975                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976                 if (wantnormals)
4977                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                 if (wanttangents)
4979                 {
4980                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982                 }
4983                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4984                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985                 if (wantnormals || wanttangents)
4986                 {
4987                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4988                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4989                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4990                 }
4991                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4992                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4993                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4994         }
4995         return true;
4996 }
4997
4998 void R_AnimCache_CacheVisibleEntities(void)
4999 {
5000         int i;
5001         qboolean wantnormals = true;
5002         qboolean wanttangents = !r_showsurfaces.integer;
5003
5004         switch(vid.renderpath)
5005         {
5006         case RENDERPATH_GL20:
5007         case RENDERPATH_D3D9:
5008         case RENDERPATH_D3D10:
5009         case RENDERPATH_D3D11:
5010         case RENDERPATH_GLES2:
5011                 break;
5012         case RENDERPATH_GL11:
5013         case RENDERPATH_GL13:
5014         case RENDERPATH_GLES1:
5015                 wanttangents = false;
5016                 break;
5017         case RENDERPATH_SOFT:
5018                 break;
5019         }
5020
5021         if (r_shownormals.integer)
5022                 wanttangents = wantnormals = true;
5023
5024         // TODO: thread this
5025         // NOTE: R_PrepareRTLights() also caches entities
5026
5027         for (i = 0;i < r_refdef.scene.numentities;i++)
5028                 if (r_refdef.viewcache.entityvisible[i])
5029                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5030 }
5031
5032 //==================================================================================
5033
5034 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5035 {
5036         int i;
5037         vec3_t eyemins, eyemaxs;
5038         vec3_t boxmins, boxmaxs;
5039         vec3_t padmins, padmaxs;
5040         vec3_t start;
5041         vec3_t end;
5042         dp_model_t *model = r_refdef.scene.worldmodel;
5043         static vec3_t positions[] = {
5044                 { 0.5f, 0.5f, 0.5f },
5045                 { 0.0f, 0.0f, 0.0f },
5046                 { 0.0f, 0.0f, 1.0f },
5047                 { 0.0f, 1.0f, 0.0f },
5048                 { 0.0f, 1.0f, 1.0f },
5049                 { 1.0f, 0.0f, 0.0f },
5050                 { 1.0f, 0.0f, 1.0f },
5051                 { 1.0f, 1.0f, 0.0f },
5052                 { 1.0f, 1.0f, 1.0f },
5053         };
5054
5055         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5056         if (numsamples < 0)
5057                 return true;
5058
5059         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5060         if (!r_refdef.view.usevieworiginculling)
5061                 return true;
5062
5063         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5064                 return true;
5065
5066         // expand the eye box a little
5067         eyemins[0] = eye[0] - eyejitter;
5068         eyemaxs[0] = eye[0] + eyejitter;
5069         eyemins[1] = eye[1] - eyejitter;
5070         eyemaxs[1] = eye[1] + eyejitter;
5071         eyemins[2] = eye[2] - eyejitter;
5072         eyemaxs[2] = eye[2] + eyejitter;
5073         // expand the box a little
5074         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
5075         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
5076         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
5077         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
5078         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
5079         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
5080         // make an even larger box for the acceptable area
5081         padmins[0] = boxmins[0] - pad;
5082         padmaxs[0] = boxmaxs[0] + pad;
5083         padmins[1] = boxmins[1] - pad;
5084         padmaxs[1] = boxmaxs[1] + pad;
5085         padmins[2] = boxmins[2] - pad;
5086         padmaxs[2] = boxmaxs[2] + pad;
5087
5088         // return true if eye overlaps enlarged box
5089         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5090                 return true;
5091
5092         // try specific positions in the box first - note that these can be cached
5093         if (r_cullentities_trace_entityocclusion.integer)
5094         {
5095                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5096                 {
5097                         VectorCopy(eye, start);
5098                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5099                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5100                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5101                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5102                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5103                         // not picky - if the trace ended anywhere in the box we're good
5104                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5105                                 return true;
5106                 }
5107         }
5108         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5109                 return true;
5110
5111         // try various random positions
5112         for (i = 0; i < numsamples; i++)
5113         {
5114                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5115                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5116                 if (r_cullentities_trace_entityocclusion.integer)
5117                 {
5118                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5119                         // not picky - if the trace ended anywhere in the box we're good
5120                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5121                                 return true;
5122                 }
5123                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5124                         return true;
5125         }
5126
5127         return false;
5128 }
5129
5130
5131 static void R_View_UpdateEntityVisible (void)
5132 {
5133         int i;
5134         int renderimask;
5135         int samples;
5136         entity_render_t *ent;
5137
5138         if (r_refdef.envmap || r_fb.water.hideplayer)
5139                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5140         else if (chase_active.integer || r_fb.water.renderingscene)
5141                 renderimask = RENDER_VIEWMODEL;
5142         else
5143                 renderimask = RENDER_EXTERIORMODEL;
5144         if (!r_drawviewmodel.integer)
5145                 renderimask |= RENDER_VIEWMODEL;
5146         if (!r_drawexteriormodel.integer)
5147                 renderimask |= RENDER_EXTERIORMODEL;
5148         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5149         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5150         {
5151                 // worldmodel can check visibility
5152                 for (i = 0;i < r_refdef.scene.numentities;i++)
5153                 {
5154                         ent = r_refdef.scene.entities[i];
5155                         if (!(ent->flags & renderimask))
5156                         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)))
5157                         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))
5158                                 r_refdef.viewcache.entityvisible[i] = true;
5159                 }
5160         }
5161         else
5162         {
5163                 // no worldmodel or it can't check visibility
5164                 for (i = 0;i < r_refdef.scene.numentities;i++)
5165                 {
5166                         ent = r_refdef.scene.entities[i];
5167                         if (!(ent->flags & renderimask))
5168                         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)))
5169                                 r_refdef.viewcache.entityvisible[i] = true;
5170                 }
5171         }
5172         if (r_cullentities_trace.integer)
5173         {
5174                 for (i = 0;i < r_refdef.scene.numentities;i++)
5175                 {
5176                         if (!r_refdef.viewcache.entityvisible[i])
5177                                 continue;
5178                         ent = r_refdef.scene.entities[i];
5179                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5180                         {
5181                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5182                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_cullentities_trace_expand.value, r_cullentities_trace_pad.value, r_refdef.view.origin, ent->mins, ent->maxs))
5183                                         ent->last_trace_visibility = realtime;
5184                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5185                                         r_refdef.viewcache.entityvisible[i] = 0;
5186                         }
5187                 }
5188         }
5189 }
5190
5191 /// only used if skyrendermasked, and normally returns false
5192 static int R_DrawBrushModelsSky (void)
5193 {
5194         int i, sky;
5195         entity_render_t *ent;
5196
5197         sky = false;
5198         for (i = 0;i < r_refdef.scene.numentities;i++)
5199         {
5200                 if (!r_refdef.viewcache.entityvisible[i])
5201                         continue;
5202                 ent = r_refdef.scene.entities[i];
5203                 if (!ent->model || !ent->model->DrawSky)
5204                         continue;
5205                 ent->model->DrawSky(ent);
5206                 sky = true;
5207         }
5208         return sky;
5209 }
5210
5211 static void R_DrawNoModel(entity_render_t *ent);
5212 static void R_DrawModels(void)
5213 {
5214         int i;
5215         entity_render_t *ent;
5216
5217         for (i = 0;i < r_refdef.scene.numentities;i++)
5218         {
5219                 if (!r_refdef.viewcache.entityvisible[i])
5220                         continue;
5221                 ent = r_refdef.scene.entities[i];
5222                 r_refdef.stats[r_stat_entities]++;
5223                 /*
5224                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5225                 {
5226                         vec3_t f, l, u, o;
5227                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5228                         Con_Printf("R_DrawModels\n");
5229                         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]);
5230                         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);
5231                         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);
5232                 }
5233                 */
5234                 if (ent->model && ent->model->Draw != NULL)
5235                         ent->model->Draw(ent);
5236                 else
5237                         R_DrawNoModel(ent);
5238         }
5239 }
5240
5241 static void R_DrawModelsDepth(void)
5242 {
5243         int i;
5244         entity_render_t *ent;
5245
5246         for (i = 0;i < r_refdef.scene.numentities;i++)
5247         {
5248                 if (!r_refdef.viewcache.entityvisible[i])
5249                         continue;
5250                 ent = r_refdef.scene.entities[i];
5251                 if (ent->model && ent->model->DrawDepth != NULL)
5252                         ent->model->DrawDepth(ent);
5253         }
5254 }
5255
5256 static void R_DrawModelsDebug(void)
5257 {
5258         int i;
5259         entity_render_t *ent;
5260
5261         for (i = 0;i < r_refdef.scene.numentities;i++)
5262         {
5263                 if (!r_refdef.viewcache.entityvisible[i])
5264                         continue;
5265                 ent = r_refdef.scene.entities[i];
5266                 if (ent->model && ent->model->DrawDebug != NULL)
5267                         ent->model->DrawDebug(ent);
5268         }
5269 }
5270
5271 static void R_DrawModelsAddWaterPlanes(void)
5272 {
5273         int i;
5274         entity_render_t *ent;
5275
5276         for (i = 0;i < r_refdef.scene.numentities;i++)
5277         {
5278                 if (!r_refdef.viewcache.entityvisible[i])
5279                         continue;
5280                 ent = r_refdef.scene.entities[i];
5281                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5282                         ent->model->DrawAddWaterPlanes(ent);
5283         }
5284 }
5285
5286 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}};
5287
5288 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5289 {
5290         if (r_hdr_irisadaptation.integer)
5291         {
5292                 vec3_t p;
5293                 vec3_t ambient;
5294                 vec3_t diffuse;
5295                 vec3_t diffusenormal;
5296                 vec3_t forward;
5297                 vec_t brightness = 0.0f;
5298                 vec_t goal;
5299                 vec_t current;
5300                 vec_t d;
5301                 int c;
5302                 VectorCopy(r_refdef.view.forward, forward);
5303                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5304                 {
5305                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5306                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5307                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5308                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5309                         d = DotProduct(forward, diffusenormal);
5310                         brightness += VectorLength(ambient);
5311                         if (d > 0)
5312                                 brightness += d * VectorLength(diffuse);
5313                 }
5314                 brightness *= 1.0f / c;
5315                 brightness += 0.00001f; // make sure it's never zero
5316                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5317                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5318                 current = r_hdr_irisadaptation_value.value;
5319                 if (current < goal)
5320                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5321                 else if (current > goal)
5322                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5323                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5324                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5325         }
5326         else if (r_hdr_irisadaptation_value.value != 1.0f)
5327                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5328 }
5329
5330 static void R_View_SetFrustum(const int *scissor)
5331 {
5332         int i;
5333         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5334         vec3_t forward, left, up, origin, v;
5335
5336         if(scissor)
5337         {
5338                 // flipped x coordinates (because x points left here)
5339                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5340                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5341
5342                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5343                 switch(vid.renderpath)
5344                 {
5345                         case RENDERPATH_D3D9:
5346                         case RENDERPATH_D3D10:
5347                         case RENDERPATH_D3D11:
5348                                 // non-flipped y coordinates
5349                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5350                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5351                                 break;
5352                         case RENDERPATH_SOFT:
5353                         case RENDERPATH_GL11:
5354                         case RENDERPATH_GL13:
5355                         case RENDERPATH_GL20:
5356                         case RENDERPATH_GLES1:
5357                         case RENDERPATH_GLES2:
5358                                 // non-flipped y coordinates
5359                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5360                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361                                 break;
5362                 }
5363         }
5364
5365         // we can't trust r_refdef.view.forward and friends in reflected scenes
5366         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5367
5368 #if 0
5369         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5370         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5371         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5372         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5373         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5374         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5375         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5376         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5377         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5378         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5379         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5380         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5381 #endif
5382
5383 #if 0
5384         zNear = r_refdef.nearclip;
5385         nudge = 1.0 - 1.0 / (1<<23);
5386         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5387         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5388         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5389         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5390         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5391         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5392         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5393         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5394 #endif
5395
5396
5397
5398 #if 0
5399         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5400         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5401         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5402         r_refdef.view.frustum[0].dist = m[15] - m[12];
5403
5404         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5405         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5406         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5407         r_refdef.view.frustum[1].dist = m[15] + m[12];
5408
5409         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5410         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5411         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5412         r_refdef.view.frustum[2].dist = m[15] - m[13];
5413
5414         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5415         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5416         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5417         r_refdef.view.frustum[3].dist = m[15] + m[13];
5418
5419         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5420         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5421         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5422         r_refdef.view.frustum[4].dist = m[15] - m[14];
5423
5424         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5425         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5426         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5427         r_refdef.view.frustum[5].dist = m[15] + m[14];
5428 #endif
5429
5430         if (r_refdef.view.useperspective)
5431         {
5432                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5433                 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]);
5434                 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]);
5435                 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]);
5436                 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]);
5437
5438                 // then the normals from the corners relative to origin
5439                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5440                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5441                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5442                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5443
5444                 // in a NORMAL view, forward cross left == up
5445                 // in a REFLECTED view, forward cross left == down
5446                 // so our cross products above need to be adjusted for a left handed coordinate system
5447                 CrossProduct(forward, left, v);
5448                 if(DotProduct(v, up) < 0)
5449                 {
5450                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5451                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5452                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5453                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5454                 }
5455
5456                 // Leaving those out was a mistake, those were in the old code, and they
5457                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5458                 // I couldn't reproduce it after adding those normalizations. --blub
5459                 VectorNormalize(r_refdef.view.frustum[0].normal);
5460                 VectorNormalize(r_refdef.view.frustum[1].normal);
5461                 VectorNormalize(r_refdef.view.frustum[2].normal);
5462                 VectorNormalize(r_refdef.view.frustum[3].normal);
5463
5464                 // make the corners absolute
5465                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5466                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5467                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5468                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5469
5470                 // one more normal
5471                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5472
5473                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5474                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5475                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5476                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5477                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5478         }
5479         else
5480         {
5481                 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
5482                 VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
5483                 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
5484                 VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
5485                 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
5486                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
5487                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
5488                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
5489                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
5490                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
5491         }
5492         r_refdef.view.numfrustumplanes = 5;
5493
5494         if (r_refdef.view.useclipplane)
5495         {
5496                 r_refdef.view.numfrustumplanes = 6;
5497                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5498         }
5499
5500         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5501                 PlaneClassify(r_refdef.view.frustum + i);
5502
5503         // LordHavoc: note to all quake engine coders, Quake had a special case
5504         // for 90 degrees which assumed a square view (wrong), so I removed it,
5505         // Quake2 has it disabled as well.
5506
5507         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5508         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5509         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5510         //PlaneClassify(&frustum[0]);
5511
5512         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5513         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5514         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5515         //PlaneClassify(&frustum[1]);
5516
5517         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5518         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5519         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5520         //PlaneClassify(&frustum[2]);
5521
5522         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5523         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5524         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5525         //PlaneClassify(&frustum[3]);
5526
5527         // nearclip plane
5528         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5529         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5530         //PlaneClassify(&frustum[4]);
5531 }
5532
5533 static void R_View_UpdateWithScissor(const int *myscissor)
5534 {
5535         R_Main_ResizeViewCache();
5536         R_View_SetFrustum(myscissor);
5537         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
5538         R_View_UpdateEntityVisible();
5539 }
5540
5541 static void R_View_Update(void)
5542 {
5543         R_Main_ResizeViewCache();
5544         R_View_SetFrustum(NULL);
5545         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
5546         R_View_UpdateEntityVisible();
5547 }
5548
5549 float viewscalefpsadjusted = 1.0f;
5550
5551 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5552 {
5553         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5554         scale = bound(0.03125f, scale, 1.0f);
5555         *outwidth = (int)ceil(width * scale);
5556         *outheight = (int)ceil(height * scale);
5557 }
5558
5559 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5560 {
5561         const float *customclipplane = NULL;
5562         float plane[4];
5563         int /*rtwidth,*/ rtheight;
5564         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5565         {
5566                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5567                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5568                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5569                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5570                         dist = r_refdef.view.clipplane.dist;
5571                 plane[0] = r_refdef.view.clipplane.normal[0];
5572                 plane[1] = r_refdef.view.clipplane.normal[1];
5573                 plane[2] = r_refdef.view.clipplane.normal[2];
5574                 plane[3] = -dist;
5575                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5576         }
5577
5578         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5579         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5580
5581         if (!r_refdef.view.useperspective)
5582                 R_Viewport_InitOrtho3D(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5583         else if (vid.stencil && r_useinfinitefarclip.integer)
5584                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5585         else
5586                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5587         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5588         R_SetViewport(&r_refdef.view.viewport);
5589         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5590         {
5591                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5592                 float screenplane[4];
5593                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5594                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5595                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5596                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5597                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5598         }
5599 }
5600
5601 void R_EntityMatrix(const matrix4x4_t *matrix)
5602 {
5603         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5604         {
5605                 gl_modelmatrixchanged = false;
5606                 gl_modelmatrix = *matrix;
5607                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5608                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5609                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5610                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5611                 CHECKGLERROR
5612                 switch(vid.renderpath)
5613                 {
5614                 case RENDERPATH_D3D9:
5615 #ifdef SUPPORTD3D
5616                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5617                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5618 #endif
5619                         break;
5620                 case RENDERPATH_D3D10:
5621                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5622                         break;
5623                 case RENDERPATH_D3D11:
5624                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5625                         break;
5626                 case RENDERPATH_GL11:
5627                 case RENDERPATH_GL13:
5628                 case RENDERPATH_GLES1:
5629 #ifndef USE_GLES2
5630                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5631 #endif
5632                         break;
5633                 case RENDERPATH_SOFT:
5634                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5635                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5636                         break;
5637                 case RENDERPATH_GL20:
5638                 case RENDERPATH_GLES2:
5639                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5640                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5641                         break;
5642                 }
5643         }
5644 }
5645
5646 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5647 {
5648         r_viewport_t viewport;
5649
5650         CHECKGLERROR
5651
5652         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5653         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5654         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5655         R_SetViewport(&viewport);
5656         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5657         GL_Color(1, 1, 1, 1);
5658         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5659         GL_BlendFunc(GL_ONE, GL_ZERO);
5660         GL_ScissorTest(false);
5661         GL_DepthMask(false);
5662         GL_DepthRange(0, 1);
5663         GL_DepthTest(false);
5664         GL_DepthFunc(GL_LEQUAL);
5665         R_EntityMatrix(&identitymatrix);
5666         R_Mesh_ResetTextureState();
5667         GL_PolygonOffset(0, 0);
5668         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5669         switch(vid.renderpath)
5670         {
5671         case RENDERPATH_GL11:
5672         case RENDERPATH_GL13:
5673         case RENDERPATH_GL20:
5674         case RENDERPATH_GLES1:
5675         case RENDERPATH_GLES2:
5676                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5677                 break;
5678         case RENDERPATH_D3D9:
5679         case RENDERPATH_D3D10:
5680         case RENDERPATH_D3D11:
5681         case RENDERPATH_SOFT:
5682                 break;
5683         }
5684         GL_CullFace(GL_NONE);
5685
5686         CHECKGLERROR
5687 }
5688
5689 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5690 {
5691         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5692 }
5693
5694 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5695 {
5696         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5697         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5698         GL_Color(1, 1, 1, 1);
5699         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5700         GL_BlendFunc(GL_ONE, GL_ZERO);
5701         GL_ScissorTest(true);
5702         GL_DepthMask(true);
5703         GL_DepthRange(0, 1);
5704         GL_DepthTest(true);
5705         GL_DepthFunc(GL_LEQUAL);
5706         R_EntityMatrix(&identitymatrix);
5707         R_Mesh_ResetTextureState();
5708         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5709         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5710         switch(vid.renderpath)
5711         {
5712         case RENDERPATH_GL11:
5713         case RENDERPATH_GL13:
5714         case RENDERPATH_GL20:
5715         case RENDERPATH_GLES1:
5716         case RENDERPATH_GLES2:
5717                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5718                 break;
5719         case RENDERPATH_D3D9:
5720         case RENDERPATH_D3D10:
5721         case RENDERPATH_D3D11:
5722         case RENDERPATH_SOFT:
5723                 break;
5724         }
5725         GL_CullFace(r_refdef.view.cullface_back);
5726 }
5727
5728 /*
5729 ================
5730 R_RenderView_UpdateViewVectors
5731 ================
5732 */
5733 void R_RenderView_UpdateViewVectors(void)
5734 {
5735         // break apart the view matrix into vectors for various purposes
5736         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5737         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5738         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5739         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5740         // make an inverted copy of the view matrix for tracking sprites
5741         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5742 }
5743
5744 void R_RenderTarget_FreeUnused(qboolean force)
5745 {
5746         int i, j, end;
5747         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5748         for (i = 0; i < end; i++)
5749         {
5750                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5751                 // free resources for rendertargets that have not been used for a while
5752                 // (note: this check is run after the frame render, so any targets used
5753                 // this frame will not be affected even at low framerates)
5754                 if (r && (realtime - r->lastusetime > 0.2 || force))
5755                 {
5756                         if (r->fbo)
5757                                 R_Mesh_DestroyFramebufferObject(r->fbo);
5758                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5759                                 if (r->colortexture[j])
5760                                         R_FreeTexture(r->colortexture[j]);
5761                         if (r->depthtexture)
5762                                 R_FreeTexture(r->depthtexture);
5763                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5764                 }
5765         }
5766 }
5767
5768 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5769 {
5770         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5771         switch (vid.renderpath)
5772         {
5773         case RENDERPATH_D3D9:
5774                 x1 = (x + 0.5f) * iw;
5775                 x2 = (x + 0.5f + w) * iw;
5776                 y1 = (y + 0.5f) * ih;
5777                 y2 = (y + 0.5f + h) * ih;
5778                 break;
5779         default:
5780                 x1 = x * iw;
5781                 x2 = (x + w) * iw;
5782                 y1 = (th - y) * ih;
5783                 y2 = (th - y - h) * ih;
5784                 break;
5785         }
5786         texcoord2f[0] = x1;
5787         texcoord2f[2] = x2;
5788         texcoord2f[4] = x2;
5789         texcoord2f[6] = x1;
5790         texcoord2f[1] = y1;
5791         texcoord2f[3] = y1;
5792         texcoord2f[5] = y2;
5793         texcoord2f[7] = y2;
5794 }
5795
5796 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5797 {
5798         int i, j, end;
5799         r_rendertarget_t *r = NULL;
5800         char vabuf[256];
5801         // first try to reuse an existing slot if possible
5802         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5803         for (i = 0; i < end; i++)
5804         {
5805                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5806                 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5807                         break;
5808         }
5809         if (i == end)
5810         {
5811                 // no unused exact match found, so we have to make one in the first unused slot
5812                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5813                 r->texturewidth = texturewidth;
5814                 r->textureheight = textureheight;
5815                 r->colortextype[0] = colortextype0;
5816                 r->colortextype[1] = colortextype1;
5817                 r->colortextype[2] = colortextype2;
5818                 r->colortextype[3] = colortextype3;
5819                 r->depthtextype = depthtextype;
5820                 r->depthisrenderbuffer = depthisrenderbuffer;
5821                 for (j = 0; j < 4; j++)
5822                         if (r->colortextype[j])
5823                                 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5824                 if (r->depthtextype)
5825                 {
5826                         if (r->depthisrenderbuffer)
5827                                 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5828                         else
5829                                 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5830                 }
5831                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5832         }
5833         r_refdef.stats[r_stat_rendertargets_used]++;
5834         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5835         r->lastusetime = realtime;
5836         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5837         return r;
5838 }
5839
5840 static void R_Water_StartFrame(void)
5841 {
5842         int waterwidth, waterheight;
5843
5844         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5845                 return;
5846
5847         switch(vid.renderpath)
5848         {
5849         case RENDERPATH_GL20:
5850         case RENDERPATH_D3D9:
5851         case RENDERPATH_D3D10:
5852         case RENDERPATH_D3D11:
5853         case RENDERPATH_SOFT:
5854         case RENDERPATH_GLES2:
5855                 break;
5856         case RENDERPATH_GL11:
5857         case RENDERPATH_GL13:
5858         case RENDERPATH_GLES1:
5859                 return;
5860         }
5861
5862         // set waterwidth and waterheight to the water resolution that will be
5863         // used (often less than the screen resolution for faster rendering)
5864         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5865         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5866         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5867
5868         if (!r_water.integer || r_showsurfaces.integer)
5869                 waterwidth = waterheight = 0;
5870
5871         // set up variables that will be used in shader setup
5872         r_fb.water.waterwidth = waterwidth;
5873         r_fb.water.waterheight = waterheight;
5874         r_fb.water.texturewidth = waterwidth;
5875         r_fb.water.textureheight = waterheight;
5876         r_fb.water.camerawidth = waterwidth;
5877         r_fb.water.cameraheight = waterheight;
5878         r_fb.water.screenscale[0] = 0.5f;
5879         r_fb.water.screenscale[1] = 0.5f;
5880         r_fb.water.screencenter[0] = 0.5f;
5881         r_fb.water.screencenter[1] = 0.5f;
5882         r_fb.water.enabled = waterwidth != 0;
5883
5884         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5885         r_fb.water.numwaterplanes = 0;
5886 }
5887
5888 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5889 {
5890         int planeindex, bestplaneindex, vertexindex;
5891         vec3_t mins, maxs, normal, center, v, n;
5892         vec_t planescore, bestplanescore;
5893         mplane_t plane;
5894         r_waterstate_waterplane_t *p;
5895         texture_t *t = R_GetCurrentTexture(surface->texture);
5896
5897         rsurface.texture = t;
5898         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5899         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5900         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5901                 return;
5902         // average the vertex normals, find the surface bounds (after deformvertexes)
5903         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5904         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5905         VectorCopy(n, normal);
5906         VectorCopy(v, mins);
5907         VectorCopy(v, maxs);
5908         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5909         {
5910                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5911                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5912                 VectorAdd(normal, n, normal);
5913                 mins[0] = min(mins[0], v[0]);
5914                 mins[1] = min(mins[1], v[1]);
5915                 mins[2] = min(mins[2], v[2]);
5916                 maxs[0] = max(maxs[0], v[0]);
5917                 maxs[1] = max(maxs[1], v[1]);
5918                 maxs[2] = max(maxs[2], v[2]);
5919         }
5920         VectorNormalize(normal);
5921         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5922
5923         VectorCopy(normal, plane.normal);
5924         VectorNormalize(plane.normal);
5925         plane.dist = DotProduct(center, plane.normal);
5926         PlaneClassify(&plane);
5927         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5928         {
5929                 // skip backfaces (except if nocullface is set)
5930 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5931 //                      return;
5932                 VectorNegate(plane.normal, plane.normal);
5933                 plane.dist *= -1;
5934                 PlaneClassify(&plane);
5935         }
5936
5937
5938         // find a matching plane if there is one
5939         bestplaneindex = -1;
5940         bestplanescore = 1048576.0f;
5941         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5942         {
5943                 if(p->camera_entity == t->camera_entity)
5944                 {
5945                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5946                         if (bestplaneindex < 0 || bestplanescore > planescore)
5947                         {
5948                                 bestplaneindex = planeindex;
5949                                 bestplanescore = planescore;
5950                         }
5951                 }
5952         }
5953         planeindex = bestplaneindex;
5954
5955         // if this surface does not fit any known plane rendered this frame, add one
5956         if (planeindex < 0 || bestplanescore > 0.001f)
5957         {
5958                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5959                 {
5960                         // store the new plane
5961                         planeindex = r_fb.water.numwaterplanes++;
5962                         p = r_fb.water.waterplanes + planeindex;
5963                         p->plane = plane;
5964                         // clear materialflags and pvs
5965                         p->materialflags = 0;
5966                         p->pvsvalid = false;
5967                         p->camera_entity = t->camera_entity;
5968                         VectorCopy(mins, p->mins);
5969                         VectorCopy(maxs, p->maxs);
5970                 }
5971                 else
5972                 {
5973                         // We're totally screwed.
5974                         return;
5975                 }
5976         }
5977         else
5978         {
5979                 // merge mins/maxs when we're adding this surface to the plane
5980                 p = r_fb.water.waterplanes + planeindex;
5981                 p->mins[0] = min(p->mins[0], mins[0]);
5982                 p->mins[1] = min(p->mins[1], mins[1]);
5983                 p->mins[2] = min(p->mins[2], mins[2]);
5984                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5985                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5986                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5987         }
5988         // merge this surface's materialflags into the waterplane
5989         p->materialflags |= t->currentmaterialflags;
5990         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5991         {
5992                 // merge this surface's PVS into the waterplane
5993                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5994                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5995                 {
5996                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5997                         p->pvsvalid = true;
5998                 }
5999         }
6000 }
6001
6002 extern cvar_t r_drawparticles;
6003 extern cvar_t r_drawdecals;
6004
6005 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
6006 {
6007         int myscissor[4];
6008         r_refdef_view_t originalview;
6009         r_refdef_view_t myview;
6010         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;
6011         r_waterstate_waterplane_t *p;
6012         vec3_t visorigin;
6013         r_rendertarget_t *rt;
6014
6015         originalview = r_refdef.view;
6016
6017         // lowquality hack, temporarily shut down some cvars and restore afterwards
6018         qualityreduction = r_water_lowquality.integer;
6019         if (qualityreduction > 0)
6020         {
6021                 if (qualityreduction >= 1)
6022                 {
6023                         old_r_shadows = r_shadows.integer;
6024                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6025                         old_r_dlight = r_shadow_realtime_dlight.integer;
6026                         Cvar_SetValueQuick(&r_shadows, 0);
6027                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6028                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6029                 }
6030                 if (qualityreduction >= 2)
6031                 {
6032                         old_r_dynamic = r_dynamic.integer;
6033                         old_r_particles = r_drawparticles.integer;
6034                         old_r_decals = r_drawdecals.integer;
6035                         Cvar_SetValueQuick(&r_dynamic, 0);
6036                         Cvar_SetValueQuick(&r_drawparticles, 0);
6037                         Cvar_SetValueQuick(&r_drawdecals, 0);
6038                 }
6039         }
6040
6041         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6042         {
6043                 p->rt_reflection = NULL;
6044                 p->rt_refraction = NULL;
6045                 p->rt_camera = NULL;
6046         }
6047
6048         // render views
6049         r_refdef.view = originalview;
6050         r_refdef.view.showdebug = false;
6051         r_refdef.view.width = r_fb.water.waterwidth;
6052         r_refdef.view.height = r_fb.water.waterheight;
6053         r_refdef.view.useclipplane = true;
6054         myview = r_refdef.view;
6055         r_fb.water.renderingscene = true;
6056         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6057         {
6058                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6059                         continue;
6060
6061                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6062                 {
6063                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6064                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6065                                 goto error;
6066                         r_refdef.view = myview;
6067                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6068                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6069                         if(r_water_scissormode.integer)
6070                         {
6071                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6072                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6073                                 {
6074                                         p->rt_reflection = NULL;
6075                                         p->rt_refraction = NULL;
6076                                         p->rt_camera = NULL;
6077                                         continue;
6078                                 }
6079                         }
6080
6081                         r_refdef.view.clipplane = p->plane;
6082                         // reflected view origin may be in solid, so don't cull with it
6083                         r_refdef.view.usevieworiginculling = false;
6084                         // reverse the cullface settings for this render
6085                         r_refdef.view.cullface_front = GL_FRONT;
6086                         r_refdef.view.cullface_back = GL_BACK;
6087                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6088                         {
6089                                 r_refdef.view.usecustompvs = true;
6090                                 if (p->pvsvalid)
6091                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6092                                 else
6093                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6094                         }
6095
6096                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6097                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6098                         GL_ScissorTest(false);
6099                         R_ClearScreen(r_refdef.fogenabled);
6100                         GL_ScissorTest(true);
6101                         if(r_water_scissormode.integer & 2)
6102                                 R_View_UpdateWithScissor(myscissor);
6103                         else
6104                                 R_View_Update();
6105                         R_AnimCache_CacheVisibleEntities();
6106                         if(r_water_scissormode.integer & 1)
6107                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6108                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6109
6110                         r_fb.water.hideplayer = false;
6111                         p->rt_reflection = rt;
6112                 }
6113
6114                 // render the normal view scene and copy into texture
6115                 // (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)
6116                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6117                 {
6118                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6119                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6120                                 goto error;
6121                         r_refdef.view = myview;
6122                         if(r_water_scissormode.integer)
6123                         {
6124                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6125                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6126                                 {
6127                                         p->rt_reflection = NULL;
6128                                         p->rt_refraction = NULL;
6129                                         p->rt_camera = NULL;
6130                                         continue;
6131                                 }
6132                         }
6133
6134                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6135
6136                         r_refdef.view.clipplane = p->plane;
6137                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6138                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6139
6140                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6141                         {
6142                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6143                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6144                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6145                                 R_RenderView_UpdateViewVectors();
6146                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6147                                 {
6148                                         r_refdef.view.usecustompvs = true;
6149                                         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);
6150                                 }
6151                         }
6152
6153                         PlaneClassify(&r_refdef.view.clipplane);
6154
6155                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6156                         GL_ScissorTest(false);
6157                         R_ClearScreen(r_refdef.fogenabled);
6158                         GL_ScissorTest(true);
6159                         if(r_water_scissormode.integer & 2)
6160                                 R_View_UpdateWithScissor(myscissor);
6161                         else
6162                                 R_View_Update();
6163                         R_AnimCache_CacheVisibleEntities();
6164                         if(r_water_scissormode.integer & 1)
6165                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6166                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6167
6168                         r_fb.water.hideplayer = false;
6169                         p->rt_refraction = rt;
6170                 }
6171                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6172                 {
6173                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6174                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6175                                 goto error;
6176                         r_refdef.view = myview;
6177
6178                         r_refdef.view.clipplane = p->plane;
6179                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6180                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6181
6182                         r_refdef.view.width = r_fb.water.camerawidth;
6183                         r_refdef.view.height = r_fb.water.cameraheight;
6184                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6185                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6186                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6187                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6188
6189                         if(p->camera_entity)
6190                         {
6191                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6192                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6193                         }
6194
6195                         // note: all of the view is used for displaying... so
6196                         // there is no use in scissoring
6197
6198                         // reverse the cullface settings for this render
6199                         r_refdef.view.cullface_front = GL_FRONT;
6200                         r_refdef.view.cullface_back = GL_BACK;
6201                         // also reverse the view matrix
6202                         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
6203                         R_RenderView_UpdateViewVectors();
6204                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6205                         {
6206                                 r_refdef.view.usecustompvs = true;
6207                                 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);
6208                         }
6209                         
6210                         // camera needs no clipplane
6211                         r_refdef.view.useclipplane = false;
6212                         // TODO: is the camera origin always valid?  if so we don't need to clear this
6213                         r_refdef.view.usevieworiginculling = false;
6214
6215                         PlaneClassify(&r_refdef.view.clipplane);
6216
6217                         r_fb.water.hideplayer = false;
6218
6219                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6220                         GL_ScissorTest(false);
6221                         R_ClearScreen(r_refdef.fogenabled);
6222                         GL_ScissorTest(true);
6223                         R_View_Update();
6224                         R_AnimCache_CacheVisibleEntities();
6225                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6226
6227                         r_fb.water.hideplayer = false;
6228                         p->rt_camera = rt;
6229                 }
6230
6231         }
6232         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6233         r_fb.water.renderingscene = false;
6234         r_refdef.view = originalview;
6235         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6236         R_View_Update();
6237         R_AnimCache_CacheVisibleEntities();
6238         goto finish;
6239 error:
6240         r_refdef.view = originalview;
6241         r_fb.water.renderingscene = false;
6242         Cvar_SetValueQuick(&r_water, 0);
6243         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6244 finish:
6245         // lowquality hack, restore cvars
6246         if (qualityreduction > 0)
6247         {
6248                 if (qualityreduction >= 1)
6249                 {
6250                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6251                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6252                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6253                 }
6254                 if (qualityreduction >= 2)
6255                 {
6256                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6257                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6258                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6259                 }
6260         }
6261 }
6262
6263 static void R_Bloom_StartFrame(void)
6264 {
6265         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6266         int viewwidth, viewheight;
6267         textype_t textype = TEXTYPE_COLORBUFFER;
6268
6269         // clear the pointers to rendertargets from last frame as they're stale
6270         r_fb.rt_screen = NULL;
6271         r_fb.rt_bloom = NULL;
6272
6273         switch (vid.renderpath)
6274         {
6275         case RENDERPATH_GL20:
6276                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6277                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6278                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6279                 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6280                 if (!vid.support.ext_framebuffer_object)
6281                         return;
6282                 break;
6283         case RENDERPATH_GL11:
6284         case RENDERPATH_GL13:
6285         case RENDERPATH_GLES1:
6286                 return; // don't bother
6287         case RENDERPATH_GLES2:
6288         case RENDERPATH_D3D9:
6289         case RENDERPATH_D3D10:
6290         case RENDERPATH_D3D11:
6291                 r_fb.usedepthtextures = false;
6292                 break;
6293         case RENDERPATH_SOFT:
6294                 r_fb.usedepthtextures = true;
6295                 break;
6296         }
6297
6298         if (r_viewscale_fpsscaling.integer)
6299         {
6300                 double actualframetime;
6301                 double targetframetime;
6302                 double adjust;
6303                 actualframetime = r_refdef.lastdrawscreentime;
6304                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6305                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6306                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6307                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6308                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6309                 viewscalefpsadjusted += adjust;
6310                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6311         }
6312         else
6313                 viewscalefpsadjusted = 1.0f;
6314
6315         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6316
6317         // set bloomwidth and bloomheight to the bloom resolution that will be
6318         // used (often less than the screen resolution for faster rendering)
6319         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6320         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6321         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6322         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6323         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6324
6325         // calculate desired texture sizes
6326         screentexturewidth = viewwidth;
6327         screentextureheight = viewheight;
6328         bloomtexturewidth = r_fb.bloomwidth;
6329         bloomtextureheight = r_fb.bloomheight;
6330
6331         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))
6332         {
6333                 Cvar_SetValueQuick(&r_bloom, 0);
6334                 Cvar_SetValueQuick(&r_motionblur, 0);
6335                 Cvar_SetValueQuick(&r_damageblur, 0);
6336         }
6337
6338         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6339         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6340         {
6341                 if (r_fb.ghosttexture)
6342                         R_FreeTexture(r_fb.ghosttexture);
6343                 r_fb.ghosttexture = NULL;
6344
6345                 r_fb.screentexturewidth = screentexturewidth;
6346                 r_fb.screentextureheight = screentextureheight;
6347                 r_fb.textype = textype;
6348
6349                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6350                 {
6351                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6352                                 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);
6353                         r_fb.ghosttexture_valid = false;
6354                 }
6355         }
6356
6357         if (r_bloom.integer)
6358         {
6359                 // bloom texture is a different resolution
6360                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6361                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6362                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6363         }
6364         else
6365                 r_fb.bloomwidth = r_fb.bloomheight = 0;
6366
6367         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6368
6369         r_refdef.view.clear = true;
6370 }
6371
6372 static void R_Bloom_MakeTexture(void)
6373 {
6374         int x, range, dir;
6375         float xoffset, yoffset, r, brighten;
6376         float colorscale = r_bloom_colorscale.value;
6377         r_viewport_t bloomviewport;
6378         r_rendertarget_t *prev, *cur;
6379         textype_t textype = r_fb.rt_screen->colortextype[0];
6380
6381         r_refdef.stats[r_stat_bloom]++;
6382
6383         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6384
6385         // scale down screen texture to the bloom texture size
6386         CHECKGLERROR
6387         prev = r_fb.rt_screen;
6388         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6389         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6390         R_SetViewport(&bloomviewport);
6391         GL_CullFace(GL_NONE);
6392         GL_DepthTest(false);
6393         GL_BlendFunc(GL_ONE, GL_ZERO);
6394         GL_Color(colorscale, colorscale, colorscale, 1);
6395         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6396         // TODO: do boxfilter scale-down in shader?
6397         R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6398         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6399         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6400         // we now have a properly scaled bloom image
6401
6402         // multiply bloom image by itself as many times as desired to darken it
6403         // TODO: if people actually use this it could be done more quickly in the previous shader pass
6404         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6405         {
6406                 prev = cur;
6407                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6408                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6409                 x *= 2;
6410                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6411                 if(x <= 2)
6412                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6413                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6414                 GL_Color(1,1,1,1); // no fix factor supported here
6415                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6416                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6417                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6418                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6419         }
6420
6421         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6422         brighten = r_bloom_brighten.value;
6423         brighten = sqrt(brighten);
6424         if(range >= 1)
6425                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6426
6427         for (dir = 0;dir < 2;dir++)
6428         {
6429                 prev = cur;
6430                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6431                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6432                 // blend on at multiple vertical offsets to achieve a vertical blur
6433                 // TODO: do offset blends using GLSL
6434                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6435                 GL_BlendFunc(GL_ONE, GL_ZERO);
6436                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6437                 for (x = -range;x <= range;x++)
6438                 {
6439                         if (!dir){xoffset = 0;yoffset = x;}
6440                         else {xoffset = x;yoffset = 0;}
6441                         xoffset /= (float)prev->texturewidth;
6442                         yoffset /= (float)prev->textureheight;
6443                         // compute a texcoord array with the specified x and y offset
6444                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6445                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6446                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6447                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6448                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6449                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6450                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6451                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6452                         // this r value looks like a 'dot' particle, fading sharply to
6453                         // black at the edges
6454                         // (probably not realistic but looks good enough)
6455                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6456                         //r = brighten/(range*2+1);
6457                         r = brighten / (range * 2 + 1);
6458                         if(range >= 1)
6459                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
6460                         if (r <= 0)
6461                                 continue;
6462                         GL_Color(r, r, r, 1);
6463                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6464                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6465                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6466                         GL_BlendFunc(GL_ONE, GL_ONE);
6467                 }
6468         }
6469
6470         // now we have the bloom image, so keep track of it
6471         r_fb.rt_bloom = cur;
6472 }
6473
6474 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6475 {
6476         dpuint64 permutation;
6477         float uservecs[4][4];
6478         rtexture_t *viewtexture;
6479         rtexture_t *bloomtexture;
6480
6481         R_EntityMatrix(&identitymatrix);
6482
6483         switch (vid.renderpath)
6484         {
6485         case RENDERPATH_GL20:
6486         case RENDERPATH_D3D9:
6487         case RENDERPATH_D3D10:
6488         case RENDERPATH_D3D11:
6489         case RENDERPATH_SOFT:
6490         case RENDERPATH_GLES2:
6491                 permutation =
6492                           (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6493                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6494                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6495                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6496                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6497
6498                 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6499                 {
6500                         // declare variables
6501                         float blur_factor, blur_mouseaccel, blur_velocity;
6502                         static float blur_average; 
6503                         static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6504
6505                         // set a goal for the factoring
6506                         blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6507                                 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6508                         blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6509                                 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6510                         blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6511                                 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6512
6513                         // from the goal, pick an averaged value between goal and last value
6514                         cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6515                         blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6516
6517                         // enforce minimum amount of blur 
6518                         blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6519
6520                         //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6521
6522                         // calculate values into a standard alpha
6523                         cl.motionbluralpha = 1 - exp(-
6524                                         (
6525                                                 (r_motionblur.value * blur_factor / 80)
6526                                                 +
6527                                                 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6528                                         )
6529                                         /
6530                                         max(0.0001, cl.time - cl.oldtime) // fps independent
6531                                         );
6532
6533                         // randomization for the blur value to combat persistent ghosting
6534                         cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6535                         cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6536
6537                         // apply the blur
6538                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6539                         if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6540                         {
6541                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6542                                 GL_Color(1, 1, 1, cl.motionbluralpha);
6543                                 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6544                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6545                                 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6546                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547                                 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6548                         }
6549
6550                         // updates old view angles for next pass
6551                         VectorCopy(cl.viewangles, blur_oldangles);
6552
6553                         // copy view into the ghost texture
6554                         R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6555                         r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6556                         r_fb.ghosttexture_valid = true;
6557                 }
6558
6559                 if (r_fb.bloomwidth)
6560                 {
6561                         // make the bloom texture
6562                         R_Bloom_MakeTexture();
6563                 }
6564
6565 #if _MSC_VER >= 1400
6566 #define sscanf sscanf_s
6567 #endif
6568                 memset(uservecs, 0, sizeof(uservecs));
6569                 if (r_glsl_postprocess_uservec1_enable.integer)
6570                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6571                 if (r_glsl_postprocess_uservec2_enable.integer)
6572                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6573                 if (r_glsl_postprocess_uservec3_enable.integer)
6574                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6575                 if (r_glsl_postprocess_uservec4_enable.integer)
6576                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6577
6578                 // render to the screen fbo
6579                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6580                 GL_Color(1, 1, 1, 1);
6581                 GL_BlendFunc(GL_ONE, GL_ZERO);
6582
6583                 viewtexture = r_fb.rt_screen->colortexture[0];
6584                 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6585
6586                 if (r_rendertarget_debug.integer >= 0)
6587                 {
6588                         r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6589                         if (rt && rt->colortexture[0])
6590                         {
6591                                 viewtexture = rt->colortexture[0];
6592                                 bloomtexture = NULL;
6593                         }
6594                 }
6595
6596                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6597                 switch(vid.renderpath)
6598                 {
6599                 case RENDERPATH_GL20:
6600                 case RENDERPATH_GLES2:
6601                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6602                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
6603                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
6604                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6605                         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]);
6606                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6607                         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]);
6608                         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]);
6609                         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]);
6610                         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]);
6611                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6612                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6613                         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);
6614                         break;
6615                 case RENDERPATH_D3D9:
6616 #ifdef SUPPORTD3D
6617                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6618                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6619                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6620                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6621                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6622                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6623                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6624                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6625                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6626                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6627                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6628                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6629                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6630 #endif
6631                         break;
6632                 case RENDERPATH_D3D10:
6633                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6634                         break;
6635                 case RENDERPATH_D3D11:
6636                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6637                         break;
6638                 case RENDERPATH_SOFT:
6639                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6640                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6641                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6642                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6643                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6644                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6645                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6646                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6647                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6648                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6649                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6650                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6651                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6652                         break;
6653                 default:
6654                         break;
6655                 }
6656                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6657                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6658                 break;
6659         case RENDERPATH_GL11:
6660         case RENDERPATH_GL13:
6661         case RENDERPATH_GLES1:
6662                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6663                 {
6664                         // apply a color tint to the whole view
6665                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6666                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6667                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6668                         R_SetupShader_Generic_NoTexture(false, true);
6669                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6670                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6671                 }
6672                 break;
6673         }
6674 }
6675
6676 matrix4x4_t r_waterscrollmatrix;
6677
6678 void R_UpdateFog(void)
6679 {
6680         // Nehahra fog
6681         if (gamemode == GAME_NEHAHRA)
6682         {
6683                 if (gl_fogenable.integer)
6684                 {
6685                         r_refdef.oldgl_fogenable = true;
6686                         r_refdef.fog_density = gl_fogdensity.value;
6687                         r_refdef.fog_red = gl_fogred.value;
6688                         r_refdef.fog_green = gl_foggreen.value;
6689                         r_refdef.fog_blue = gl_fogblue.value;
6690                         r_refdef.fog_alpha = 1;
6691                         r_refdef.fog_start = 0;
6692                         r_refdef.fog_end = gl_skyclip.value;
6693                         r_refdef.fog_height = 1<<30;
6694                         r_refdef.fog_fadedepth = 128;
6695                 }
6696                 else if (r_refdef.oldgl_fogenable)
6697                 {
6698                         r_refdef.oldgl_fogenable = false;
6699                         r_refdef.fog_density = 0;
6700                         r_refdef.fog_red = 0;
6701                         r_refdef.fog_green = 0;
6702                         r_refdef.fog_blue = 0;
6703                         r_refdef.fog_alpha = 0;
6704                         r_refdef.fog_start = 0;
6705                         r_refdef.fog_end = 0;
6706                         r_refdef.fog_height = 1<<30;
6707                         r_refdef.fog_fadedepth = 128;
6708                 }
6709         }
6710
6711         // fog parms
6712         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6713         r_refdef.fog_start = max(0, r_refdef.fog_start);
6714         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6715
6716         if (r_refdef.fog_density && r_drawfog.integer)
6717         {
6718                 r_refdef.fogenabled = true;
6719                 // this is the point where the fog reaches 0.9986 alpha, which we
6720                 // consider a good enough cutoff point for the texture
6721                 // (0.9986 * 256 == 255.6)
6722                 if (r_fog_exp2.integer)
6723                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6724                 else
6725                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6726                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6727                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6728                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6729                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6730                         R_BuildFogHeightTexture();
6731                 // fog color was already set
6732                 // update the fog texture
6733                 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)
6734                         R_BuildFogTexture();
6735                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6736                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6737         }
6738         else
6739                 r_refdef.fogenabled = false;
6740
6741         // fog color
6742         if (r_refdef.fog_density)
6743         {
6744                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6745                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6746                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6747
6748                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6749                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6750                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6751                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6752
6753                 {
6754                         vec3_t fogvec;
6755                         VectorCopy(r_refdef.fogcolor, fogvec);
6756                         //   color.rgb *= ContrastBoost * SceneBrightness;
6757                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6758                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6759                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6760                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6761                 }
6762         }
6763 }
6764
6765 void R_UpdateVariables(void)
6766 {
6767         R_Textures_Frame();
6768
6769         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6770
6771         r_refdef.farclip = r_farclip_base.value;
6772         if (r_refdef.scene.worldmodel)
6773                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6774         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6775
6776         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6777                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6778         r_refdef.polygonfactor = 0;
6779         r_refdef.polygonoffset = 0;
6780         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6781         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6782
6783         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6784         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6785         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6786         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6787         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6788         if (FAKELIGHT_ENABLED)
6789         {
6790                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6791         }
6792         else if (r_refdef.scene.worldmodel)
6793         {
6794                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6795         }
6796         if (r_showsurfaces.integer)
6797         {
6798                 r_refdef.scene.rtworld = false;
6799                 r_refdef.scene.rtworldshadows = false;
6800                 r_refdef.scene.rtdlight = false;
6801                 r_refdef.scene.rtdlightshadows = false;
6802                 r_refdef.scene.lightmapintensity = 0;
6803         }
6804
6805         r_gpuskeletal = false;
6806         switch(vid.renderpath)
6807         {
6808         case RENDERPATH_GL20:
6809                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6810         case RENDERPATH_D3D9:
6811         case RENDERPATH_D3D10:
6812         case RENDERPATH_D3D11:
6813         case RENDERPATH_SOFT:
6814         case RENDERPATH_GLES2:
6815                 if(!vid_gammatables_trivial)
6816                 {
6817                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6818                         {
6819                                 // build GLSL gamma texture
6820 #define RAMPWIDTH 256
6821                                 unsigned short ramp[RAMPWIDTH * 3];
6822                                 unsigned char rampbgr[RAMPWIDTH][4];
6823                                 int i;
6824
6825                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6826
6827                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6828                                 for(i = 0; i < RAMPWIDTH; ++i)
6829                                 {
6830                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6831                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6832                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6833                                         rampbgr[i][3] = 0;
6834                                 }
6835                                 if (r_texture_gammaramps)
6836                                 {
6837                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6838                                 }
6839                                 else
6840                                 {
6841                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6842                                 }
6843                         }
6844                 }
6845                 else
6846                 {
6847                         // remove GLSL gamma texture
6848                 }
6849                 break;
6850         case RENDERPATH_GL11:
6851         case RENDERPATH_GL13:
6852         case RENDERPATH_GLES1:
6853                 break;
6854         }
6855 }
6856
6857 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6858 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6859 /*
6860 ================
6861 R_SelectScene
6862 ================
6863 */
6864 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6865         if( scenetype != r_currentscenetype ) {
6866                 // store the old scenetype
6867                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6868                 r_currentscenetype = scenetype;
6869                 // move in the new scene
6870                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6871         }
6872 }
6873
6874 /*
6875 ================
6876 R_GetScenePointer
6877 ================
6878 */
6879 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6880 {
6881         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6882         if( scenetype == r_currentscenetype ) {
6883                 return &r_refdef.scene;
6884         } else {
6885                 return &r_scenes_store[ scenetype ];
6886         }
6887 }
6888
6889 static int R_SortEntities_Compare(const void *ap, const void *bp)
6890 {
6891         const entity_render_t *a = *(const entity_render_t **)ap;
6892         const entity_render_t *b = *(const entity_render_t **)bp;
6893
6894         // 1. compare model
6895         if(a->model < b->model)
6896                 return -1;
6897         if(a->model > b->model)
6898                 return +1;
6899
6900         // 2. compare skin
6901         // TODO possibly calculate the REAL skinnum here first using
6902         // skinscenes?
6903         if(a->skinnum < b->skinnum)
6904                 return -1;
6905         if(a->skinnum > b->skinnum)
6906                 return +1;
6907
6908         // everything we compared is equal
6909         return 0;
6910 }
6911 static void R_SortEntities(void)
6912 {
6913         // below or equal 2 ents, sorting never gains anything
6914         if(r_refdef.scene.numentities <= 2)
6915                 return;
6916         // sort
6917         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6918 }
6919
6920 /*
6921 ================
6922 R_RenderView
6923 ================
6924 */
6925 int dpsoftrast_test;
6926 extern cvar_t r_shadow_bouncegrid;
6927 extern cvar_t v_isometric;
6928 extern void V_MakeViewIsometric(void);
6929 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6930 {
6931         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6932         int viewfbo = 0;
6933         rtexture_t *viewdepthtexture = NULL;
6934         rtexture_t *viewcolortexture = NULL;
6935         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6936
6937         // finish any 2D rendering that was queued
6938         DrawQ_Finish();
6939
6940         dpsoftrast_test = r_test.integer;
6941
6942         if (r_timereport_active)
6943                 R_TimeReport("start");
6944         r_textureframe++; // used only by R_GetCurrentTexture
6945         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6946
6947         if(R_CompileShader_CheckStaticParms())
6948                 R_GLSL_Restart_f();
6949
6950         if (!r_drawentities.integer)
6951                 r_refdef.scene.numentities = 0;
6952         else if (r_sortentities.integer)
6953                 R_SortEntities();
6954
6955         R_AnimCache_ClearCache();
6956
6957         /* adjust for stereo display */
6958         if(R_Stereo_Active())
6959         {
6960                 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);
6961                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6962         }
6963
6964         if (r_refdef.view.isoverlay)
6965         {
6966                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6967                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6968                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6969                 R_TimeReport("depthclear");
6970
6971                 r_refdef.view.showdebug = false;
6972
6973                 r_fb.water.enabled = false;
6974                 r_fb.water.numwaterplanes = 0;
6975
6976                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6977
6978                 r_refdef.view.matrix = originalmatrix;
6979
6980                 CHECKGLERROR
6981                 return;
6982         }
6983
6984         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6985         {
6986                 r_refdef.view.matrix = originalmatrix;
6987                 return;
6988         }
6989
6990         r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
6991         if (v_isometric.integer && r_refdef.view.ismain)
6992                 V_MakeViewIsometric();
6993
6994         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6995
6996         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6997                 // in sRGB fallback, behave similar to true sRGB: convert this
6998                 // value from linear to sRGB
6999                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7000
7001         R_RenderView_UpdateViewVectors();
7002
7003         R_Shadow_UpdateWorldLightSelection();
7004
7005         // this will set up r_fb.rt_screen
7006         R_Bloom_StartFrame();
7007
7008         // apply bloom brightness offset
7009         if(r_fb.rt_bloom)
7010                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7011
7012         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
7013         if (r_fb.rt_screen)
7014         {
7015                 viewfbo = r_fb.rt_screen->fbo;
7016                 viewdepthtexture = r_fb.rt_screen->depthtexture;
7017                 viewcolortexture = r_fb.rt_screen->colortexture[0];
7018                 viewx = 0;
7019                 viewy = 0;
7020                 viewwidth = width;
7021                 viewheight = height;
7022         }
7023
7024         R_Water_StartFrame();
7025
7026         CHECKGLERROR
7027         if (r_timereport_active)
7028                 R_TimeReport("viewsetup");
7029
7030         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7031
7032         // clear the whole fbo every frame - otherwise the driver will consider
7033         // it to be an inter-frame texture and stall in multi-gpu configurations
7034         if (r_fb.rt_screen)
7035                 GL_ScissorTest(false);
7036         R_ClearScreen(r_refdef.fogenabled);
7037         if (r_timereport_active)
7038                 R_TimeReport("viewclear");
7039
7040         r_refdef.view.clear = true;
7041
7042         r_refdef.view.showdebug = true;
7043
7044         R_View_Update();
7045         if (r_timereport_active)
7046                 R_TimeReport("visibility");
7047
7048         R_AnimCache_CacheVisibleEntities();
7049         if (r_timereport_active)
7050                 R_TimeReport("animcache");
7051
7052         R_Shadow_UpdateBounceGridTexture();
7053         if (r_timereport_active && r_shadow_bouncegrid.integer)
7054                 R_TimeReport("bouncegrid");
7055
7056         r_fb.water.numwaterplanes = 0;
7057         if (r_fb.water.enabled)
7058                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7059
7060         // for the actual view render we use scissoring a fair amount, so scissor
7061         // test needs to be on
7062         if (r_fb.rt_screen)
7063                 GL_ScissorTest(true);
7064         GL_Scissor(viewx, viewy, viewwidth, viewheight);
7065         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7066         r_fb.water.numwaterplanes = 0;
7067
7068         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7069         GL_ScissorTest(false);
7070
7071         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7072         if (r_timereport_active)
7073                 R_TimeReport("blendview");
7074
7075         r_refdef.view.matrix = originalmatrix;
7076
7077         CHECKGLERROR
7078
7079         // go back to 2d rendering
7080         DrawQ_Start();
7081 }
7082
7083 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7084 {
7085         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7086         {
7087                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7088                 if (r_timereport_active)
7089                         R_TimeReport("waterworld");
7090         }
7091
7092         // don't let sound skip if going slow
7093         if (r_refdef.scene.extraupdate)
7094                 S_ExtraUpdate ();
7095
7096         R_DrawModelsAddWaterPlanes();
7097         if (r_timereport_active)
7098                 R_TimeReport("watermodels");
7099
7100         if (r_fb.water.numwaterplanes)
7101         {
7102                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7103                 if (r_timereport_active)
7104                         R_TimeReport("waterscenes");
7105         }
7106 }
7107
7108 extern cvar_t cl_locs_show;
7109 static void R_DrawLocs(void);
7110 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7111 static void R_DrawModelDecals(void);
7112 extern cvar_t cl_decals_newsystem;
7113 extern qboolean r_shadow_usingdeferredprepass;
7114 extern int r_shadow_shadowmapatlas_modelshadows_size;
7115 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7116 {
7117         qboolean shadowmapping = false;
7118
7119         if (r_timereport_active)
7120                 R_TimeReport("beginscene");
7121
7122         r_refdef.stats[r_stat_renders]++;
7123
7124         R_UpdateFog();
7125
7126         // don't let sound skip if going slow
7127         if (r_refdef.scene.extraupdate)
7128                 S_ExtraUpdate ();
7129
7130         R_MeshQueue_BeginScene();
7131
7132         R_SkyStartFrame();
7133
7134         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);
7135
7136         if (r_timereport_active)
7137                 R_TimeReport("skystartframe");
7138
7139         if (cl.csqc_vidvars.drawworld)
7140         {
7141                 // don't let sound skip if going slow
7142                 if (r_refdef.scene.extraupdate)
7143                         S_ExtraUpdate ();
7144
7145                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7146                 {
7147                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7148                         if (r_timereport_active)
7149                                 R_TimeReport("worldsky");
7150                 }
7151
7152                 if (R_DrawBrushModelsSky() && r_timereport_active)
7153                         R_TimeReport("bmodelsky");
7154
7155                 if (skyrendermasked && skyrenderlater)
7156                 {
7157                         // we have to force off the water clipping plane while rendering sky
7158                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7159                         R_Sky();
7160                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7161                         if (r_timereport_active)
7162                                 R_TimeReport("sky");
7163                 }
7164         }
7165
7166         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7167         r_shadow_viewfbo = viewfbo;
7168         r_shadow_viewdepthtexture = viewdepthtexture;
7169         r_shadow_viewcolortexture = viewcolortexture;
7170         r_shadow_viewx = viewx;
7171         r_shadow_viewy = viewy;
7172         r_shadow_viewwidth = viewwidth;
7173         r_shadow_viewheight = viewheight;
7174
7175         R_Shadow_PrepareModelShadows();
7176         R_Shadow_PrepareLights();
7177         if (r_timereport_active)
7178                 R_TimeReport("preparelights");
7179
7180         // render all the shadowmaps that will be used for this view
7181         shadowmapping = R_Shadow_ShadowMappingEnabled();
7182         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7183         {
7184                 R_Shadow_DrawShadowMaps();
7185                 if (r_timereport_active)
7186                         R_TimeReport("shadowmaps");
7187         }
7188
7189         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7190         if (r_shadow_usingdeferredprepass)
7191                 R_Shadow_DrawPrepass();
7192
7193         // now we begin the forward pass of the view render
7194         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7195         {
7196                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7197                 if (r_timereport_active)
7198                         R_TimeReport("worlddepth");
7199         }
7200         if (r_depthfirst.integer >= 2)
7201         {
7202                 R_DrawModelsDepth();
7203                 if (r_timereport_active)
7204                         R_TimeReport("modeldepth");
7205         }
7206
7207         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7208         {
7209                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7210                 if (r_timereport_active)
7211                         R_TimeReport("world");
7212         }
7213
7214         // don't let sound skip if going slow
7215         if (r_refdef.scene.extraupdate)
7216                 S_ExtraUpdate ();
7217
7218         R_DrawModels();
7219         if (r_timereport_active)
7220                 R_TimeReport("models");
7221
7222         // don't let sound skip if going slow
7223         if (r_refdef.scene.extraupdate)
7224                 S_ExtraUpdate ();
7225
7226         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7227         {
7228                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7229                 R_Shadow_DrawModelShadows();
7230                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7231                 // don't let sound skip if going slow
7232                 if (r_refdef.scene.extraupdate)
7233                         S_ExtraUpdate ();
7234         }
7235
7236         if (!r_shadow_usingdeferredprepass)
7237         {
7238                 R_Shadow_DrawLights();
7239                 if (r_timereport_active)
7240                         R_TimeReport("rtlights");
7241         }
7242
7243         // don't let sound skip if going slow
7244         if (r_refdef.scene.extraupdate)
7245                 S_ExtraUpdate ();
7246
7247         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7248         {
7249                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7250                 R_Shadow_DrawModelShadows();
7251                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7252                 // don't let sound skip if going slow
7253                 if (r_refdef.scene.extraupdate)
7254                         S_ExtraUpdate ();
7255         }
7256
7257         if (cl.csqc_vidvars.drawworld)
7258         {
7259                 if (cl_decals_newsystem.integer)
7260                 {
7261                         R_DrawModelDecals();
7262                         if (r_timereport_active)
7263                                 R_TimeReport("modeldecals");
7264                 }
7265                 else
7266                 {
7267                         R_DrawDecals();
7268                         if (r_timereport_active)
7269                                 R_TimeReport("decals");
7270                 }
7271
7272                 R_DrawParticles();
7273                 if (r_timereport_active)
7274                         R_TimeReport("particles");
7275
7276                 R_DrawExplosions();
7277                 if (r_timereport_active)
7278                         R_TimeReport("explosions");
7279         }
7280
7281         if (r_refdef.view.showdebug)
7282         {
7283                 if (cl_locs_show.integer)
7284                 {
7285                         R_DrawLocs();
7286                         if (r_timereport_active)
7287                                 R_TimeReport("showlocs");
7288                 }
7289
7290                 if (r_drawportals.integer)
7291                 {
7292                         R_DrawPortals();
7293                         if (r_timereport_active)
7294                                 R_TimeReport("portals");
7295                 }
7296
7297                 if (r_showbboxes_client.value > 0)
7298                 {
7299                         R_DrawEntityBBoxes(CLVM_prog);
7300                         if (r_timereport_active)
7301                                 R_TimeReport("clbboxes");
7302                 }
7303                 if (r_showbboxes.value > 0)
7304                 {
7305                         R_DrawEntityBBoxes(SVVM_prog);
7306                         if (r_timereport_active)
7307                                 R_TimeReport("svbboxes");
7308                 }
7309         }
7310
7311         if (r_transparent.integer)
7312         {
7313                 R_MeshQueue_RenderTransparent();
7314                 if (r_timereport_active)
7315                         R_TimeReport("drawtrans");
7316         }
7317
7318         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))
7319         {
7320                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7321                 if (r_timereport_active)
7322                         R_TimeReport("worlddebug");
7323                 R_DrawModelsDebug();
7324                 if (r_timereport_active)
7325                         R_TimeReport("modeldebug");
7326         }
7327
7328         if (cl.csqc_vidvars.drawworld)
7329         {
7330                 R_Shadow_DrawCoronas();
7331                 if (r_timereport_active)
7332                         R_TimeReport("coronas");
7333         }
7334
7335 #if 0
7336         {
7337                 GL_DepthTest(false);
7338                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7339                 GL_Color(1, 1, 1, 1);
7340                 qglBegin(GL_POLYGON);
7341                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7342                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7343                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7344                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7345                 qglEnd();
7346                 qglBegin(GL_POLYGON);
7347                 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]);
7348                 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]);
7349                 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]);
7350                 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]);
7351                 qglEnd();
7352                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7353         }
7354 #endif
7355
7356         // don't let sound skip if going slow
7357         if (r_refdef.scene.extraupdate)
7358                 S_ExtraUpdate ();
7359 }
7360
7361 static const unsigned short bboxelements[36] =
7362 {
7363         5, 1, 3, 5, 3, 7,
7364         6, 2, 0, 6, 0, 4,
7365         7, 3, 2, 7, 2, 6,
7366         4, 0, 1, 4, 1, 5,
7367         4, 5, 7, 4, 7, 6,
7368         1, 0, 2, 1, 2, 3,
7369 };
7370
7371 #define BBOXEDGES 13
7372 static const float bboxedges[BBOXEDGES][6] = 
7373 {
7374         // whole box
7375         { 0, 0, 0, 1, 1, 1 },
7376         // bottom edges
7377         { 0, 0, 0, 0, 1, 0 },
7378         { 0, 0, 0, 1, 0, 0 },
7379         { 0, 1, 0, 1, 1, 0 },
7380         { 1, 0, 0, 1, 1, 0 },
7381         // top edges
7382         { 0, 0, 1, 0, 1, 1 },
7383         { 0, 0, 1, 1, 0, 1 },
7384         { 0, 1, 1, 1, 1, 1 },
7385         { 1, 0, 1, 1, 1, 1 },
7386         // vertical edges
7387         { 0, 0, 0, 0, 0, 1 },
7388         { 1, 0, 0, 1, 0, 1 },
7389         { 0, 1, 0, 0, 1, 1 },
7390         { 1, 1, 0, 1, 1, 1 },
7391 };
7392
7393 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7394 {
7395         int numvertices = BBOXEDGES * 8;
7396         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7397         int numtriangles = BBOXEDGES * 12;
7398         unsigned short elements[BBOXEDGES * 36];
7399         int i, edge;
7400         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7401
7402         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7403
7404         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7405         GL_DepthMask(false);
7406         GL_DepthRange(0, 1);
7407         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7408
7409         for (edge = 0; edge < BBOXEDGES; edge++)
7410         {
7411                 for (i = 0; i < 3; i++)
7412                 {
7413                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7414                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7415                 }
7416                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7417                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7418                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7419                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7420                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7421                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7422                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7423                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7424                 for (i = 0; i < 36; i++)
7425                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7426         }
7427         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7428         if (r_refdef.fogenabled)
7429         {
7430                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7431                 {
7432                         f1 = RSurf_FogVertex(v);
7433                         f2 = 1 - f1;
7434                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7435                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7436                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7437                 }
7438         }
7439         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7440         R_Mesh_ResetTextureState();
7441         R_SetupShader_Generic_NoTexture(false, false);
7442         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7443 }
7444
7445 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7446 {
7447         // hacky overloading of the parameters
7448         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7449         int i;
7450         float color[4];
7451         prvm_edict_t *edict;
7452
7453         GL_CullFace(GL_NONE);
7454         R_SetupShader_Generic_NoTexture(false, false);
7455
7456         for (i = 0;i < numsurfaces;i++)
7457         {
7458                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7459                 switch ((int)PRVM_serveredictfloat(edict, solid))
7460                 {
7461                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7462                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7463                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7464                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7465                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7466                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7467                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7468                 }
7469                 if (prog == CLVM_prog)
7470                         color[3] *= r_showbboxes_client.value;
7471                 else
7472                         color[3] *= r_showbboxes.value;
7473                 color[3] = bound(0, color[3], 1);
7474                 GL_DepthTest(!r_showdisabledepthtest.integer);
7475                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7476         }
7477 }
7478
7479 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7480 {
7481         int i;
7482         prvm_edict_t *edict;
7483         vec3_t center;
7484
7485         if (prog == NULL)
7486                 return;
7487
7488         for (i = 0; i < prog->num_edicts; i++)
7489         {
7490                 edict = PRVM_EDICT_NUM(i);
7491                 if (edict->priv.server->free)
7492                         continue;
7493                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7494                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7495                         continue;
7496                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7497                         continue;
7498                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7499                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7500         }
7501 }
7502
7503 static const int nomodelelement3i[24] =
7504 {
7505         5, 2, 0,
7506         5, 1, 2,
7507         5, 0, 3,
7508         5, 3, 1,
7509         0, 2, 4,
7510         2, 1, 4,
7511         3, 0, 4,
7512         1, 3, 4
7513 };
7514
7515 static const unsigned short nomodelelement3s[24] =
7516 {
7517         5, 2, 0,
7518         5, 1, 2,
7519         5, 0, 3,
7520         5, 3, 1,
7521         0, 2, 4,
7522         2, 1, 4,
7523         3, 0, 4,
7524         1, 3, 4
7525 };
7526
7527 static const float nomodelvertex3f[6*3] =
7528 {
7529         -16,   0,   0,
7530          16,   0,   0,
7531           0, -16,   0,
7532           0,  16,   0,
7533           0,   0, -16,
7534           0,   0,  16
7535 };
7536
7537 static const float nomodelcolor4f[6*4] =
7538 {
7539         0.0f, 0.0f, 0.5f, 1.0f,
7540         0.0f, 0.0f, 0.5f, 1.0f,
7541         0.0f, 0.5f, 0.0f, 1.0f,
7542         0.0f, 0.5f, 0.0f, 1.0f,
7543         0.5f, 0.0f, 0.0f, 1.0f,
7544         0.5f, 0.0f, 0.0f, 1.0f
7545 };
7546
7547 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7548 {
7549         int i;
7550         float f1, f2, *c;
7551         float color4f[6*4];
7552
7553         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);
7554
7555         // this is only called once per entity so numsurfaces is always 1, and
7556         // surfacelist is always {0}, so this code does not handle batches
7557
7558         if (rsurface.ent_flags & RENDER_ADDITIVE)
7559         {
7560                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7561                 GL_DepthMask(false);
7562         }
7563         else if (ent->alpha < 1)
7564         {
7565                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7566                 GL_DepthMask(false);
7567         }
7568         else
7569         {
7570                 GL_BlendFunc(GL_ONE, GL_ZERO);
7571                 GL_DepthMask(true);
7572         }
7573         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7574         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7575         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7576         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7577         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7578         for (i = 0, c = color4f;i < 6;i++, c += 4)
7579         {
7580                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7581                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7582                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7583                 c[3] *= ent->alpha;
7584         }
7585         if (r_refdef.fogenabled)
7586         {
7587                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7588                 {
7589                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7590                         f2 = 1 - f1;
7591                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7592                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7593                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7594                 }
7595         }
7596 //      R_Mesh_ResetTextureState();
7597         R_SetupShader_Generic_NoTexture(false, false);
7598         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7599         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7600 }
7601
7602 void R_DrawNoModel(entity_render_t *ent)
7603 {
7604         vec3_t org;
7605         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7606         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7607                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7608         else
7609                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7610 }
7611
7612 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7613 {
7614         vec3_t right1, right2, diff, normal;
7615
7616         VectorSubtract (org2, org1, normal);
7617
7618         // calculate 'right' vector for start
7619         VectorSubtract (r_refdef.view.origin, org1, diff);
7620         CrossProduct (normal, diff, right1);
7621         VectorNormalize (right1);
7622
7623         // calculate 'right' vector for end
7624         VectorSubtract (r_refdef.view.origin, org2, diff);
7625         CrossProduct (normal, diff, right2);
7626         VectorNormalize (right2);
7627
7628         vert[ 0] = org1[0] + width * right1[0];
7629         vert[ 1] = org1[1] + width * right1[1];
7630         vert[ 2] = org1[2] + width * right1[2];
7631         vert[ 3] = org1[0] - width * right1[0];
7632         vert[ 4] = org1[1] - width * right1[1];
7633         vert[ 5] = org1[2] - width * right1[2];
7634         vert[ 6] = org2[0] - width * right2[0];
7635         vert[ 7] = org2[1] - width * right2[1];
7636         vert[ 8] = org2[2] - width * right2[2];
7637         vert[ 9] = org2[0] + width * right2[0];
7638         vert[10] = org2[1] + width * right2[1];
7639         vert[11] = org2[2] + width * right2[2];
7640 }
7641
7642 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)
7643 {
7644         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7645         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7646         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7647         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7648         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7649         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7650         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7651         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7652         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7653         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7654         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7655         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7656 }
7657
7658 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7659 {
7660         int i;
7661         float *vertex3f;
7662         float v[3];
7663         VectorSet(v, x, y, z);
7664         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7665                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7666                         break;
7667         if (i == mesh->numvertices)
7668         {
7669                 if (mesh->numvertices < mesh->maxvertices)
7670                 {
7671                         VectorCopy(v, vertex3f);
7672                         mesh->numvertices++;
7673                 }
7674                 return mesh->numvertices;
7675         }
7676         else
7677                 return i;
7678 }
7679
7680 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7681 {
7682         int i;
7683         int *e, element[3];
7684         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7685         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7686         e = mesh->element3i + mesh->numtriangles * 3;
7687         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7688         {
7689                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7690                 if (mesh->numtriangles < mesh->maxtriangles)
7691                 {
7692                         *e++ = element[0];
7693                         *e++ = element[1];
7694                         *e++ = element[2];
7695                         mesh->numtriangles++;
7696                 }
7697                 element[1] = element[2];
7698         }
7699 }
7700
7701 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7702 {
7703         int i;
7704         int *e, element[3];
7705         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7706         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7707         e = mesh->element3i + mesh->numtriangles * 3;
7708         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7709         {
7710                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7711                 if (mesh->numtriangles < mesh->maxtriangles)
7712                 {
7713                         *e++ = element[0];
7714                         *e++ = element[1];
7715                         *e++ = element[2];
7716                         mesh->numtriangles++;
7717                 }
7718                 element[1] = element[2];
7719         }
7720 }
7721
7722 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7723 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7724 {
7725         int planenum, planenum2;
7726         int w;
7727         int tempnumpoints;
7728         mplane_t *plane, *plane2;
7729         double maxdist;
7730         double temppoints[2][256*3];
7731         // figure out how large a bounding box we need to properly compute this brush
7732         maxdist = 0;
7733         for (w = 0;w < numplanes;w++)
7734                 maxdist = max(maxdist, fabs(planes[w].dist));
7735         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7736         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7737         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7738         {
7739                 w = 0;
7740                 tempnumpoints = 4;
7741                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7742                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7743                 {
7744                         if (planenum2 == planenum)
7745                                 continue;
7746                         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);
7747                         w = !w;
7748                 }
7749                 if (tempnumpoints < 3)
7750                         continue;
7751                 // generate elements forming a triangle fan for this polygon
7752                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7753         }
7754 }
7755
7756 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)
7757 {
7758         texturelayer_t *layer;
7759         layer = t->currentlayers + t->currentnumlayers++;
7760         layer->type = type;
7761         layer->depthmask = depthmask;
7762         layer->blendfunc1 = blendfunc1;
7763         layer->blendfunc2 = blendfunc2;
7764         layer->texture = texture;
7765         layer->texmatrix = *matrix;
7766         layer->color[0] = r;
7767         layer->color[1] = g;
7768         layer->color[2] = b;
7769         layer->color[3] = a;
7770 }
7771
7772 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7773 {
7774         if(parms[0] == 0 && parms[1] == 0)
7775                 return false;
7776         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7777                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7778                         return false;
7779         return true;
7780 }
7781
7782 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7783 {
7784         double index, f;
7785         index = parms[2] + rsurface.shadertime * parms[3];
7786         index -= floor(index);
7787         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7788         {
7789         default:
7790         case Q3WAVEFUNC_NONE:
7791         case Q3WAVEFUNC_NOISE:
7792         case Q3WAVEFUNC_COUNT:
7793                 f = 0;
7794                 break;
7795         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7796         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7797         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7798         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7799         case Q3WAVEFUNC_TRIANGLE:
7800                 index *= 4;
7801                 f = index - floor(index);
7802                 if (index < 1)
7803                 {
7804                         // f = f;
7805                 }
7806                 else if (index < 2)
7807                         f = 1 - f;
7808                 else if (index < 3)
7809                         f = -f;
7810                 else
7811                         f = -(1 - f);
7812                 break;
7813         }
7814         f = parms[0] + parms[1] * f;
7815         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7816                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7817         return (float) f;
7818 }
7819
7820 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7821 {
7822         int w, h, idx;
7823         float shadertime;
7824         float f;
7825         float offsetd[2];
7826         float tcmat[12];
7827         matrix4x4_t matrix, temp;
7828         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7829         // it's better to have one huge fixup every 9 hours than gradual
7830         // degradation over time which looks consistently bad after many hours.
7831         //
7832         // tcmod scroll in particular suffers from this degradation which can't be
7833         // effectively worked around even with floor() tricks because we don't
7834         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7835         // a workaround involving floor() would be incorrect anyway...
7836         shadertime = rsurface.shadertime;
7837         if (shadertime >= 32768.0f)
7838                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7839         switch(tcmod->tcmod)
7840         {
7841                 case Q3TCMOD_COUNT:
7842                 case Q3TCMOD_NONE:
7843                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7844                                 matrix = r_waterscrollmatrix;
7845                         else
7846                                 matrix = identitymatrix;
7847                         break;
7848                 case Q3TCMOD_ENTITYTRANSLATE:
7849                         // this is used in Q3 to allow the gamecode to control texcoord
7850                         // scrolling on the entity, which is not supported in darkplaces yet.
7851                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7852                         break;
7853                 case Q3TCMOD_ROTATE:
7854                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7855                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7856                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7857                         break;
7858                 case Q3TCMOD_SCALE:
7859                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7860                         break;
7861                 case Q3TCMOD_SCROLL:
7862                         // this particular tcmod is a "bug for bug" compatible one with regards to
7863                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7864                         // specifically did the wrapping and so we must mimic that...
7865                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7866                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7867                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7868                         break;
7869                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7870                         w = (int) tcmod->parms[0];
7871                         h = (int) tcmod->parms[1];
7872                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7873                         f = f - floor(f);
7874                         idx = (int) floor(f * w * h);
7875                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7876                         break;
7877                 case Q3TCMOD_STRETCH:
7878                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7879                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7880                         break;
7881                 case Q3TCMOD_TRANSFORM:
7882                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7883                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7884                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7885                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7886                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7887                         break;
7888                 case Q3TCMOD_TURBULENT:
7889                         // this is handled in the RSurf_PrepareVertices function
7890                         matrix = identitymatrix;
7891                         break;
7892         }
7893         temp = *texmatrix;
7894         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7895 }
7896
7897 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7898 {
7899         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7900         char name[MAX_QPATH];
7901         skinframe_t *skinframe;
7902         unsigned char pixels[296*194];
7903         strlcpy(cache->name, skinname, sizeof(cache->name));
7904         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7905         if (developer_loading.integer)
7906                 Con_Printf("loading %s\n", name);
7907         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7908         if (!skinframe || !skinframe->base)
7909         {
7910                 unsigned char *f;
7911                 fs_offset_t filesize;
7912                 skinframe = NULL;
7913                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7914                 if (f)
7915                 {
7916                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7917                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7918                         Mem_Free(f);
7919                 }
7920         }
7921         cache->skinframe = skinframe;
7922 }
7923
7924 texture_t *R_GetCurrentTexture(texture_t *t)
7925 {
7926         int i, q;
7927         const entity_render_t *ent = rsurface.entity;
7928         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7929         q3shaderinfo_layer_tcmod_t *tcmod;
7930         float specularscale = 0.0f;
7931
7932         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7933                 return t->currentframe;
7934         t->update_lastrenderframe = r_textureframe;
7935         t->update_lastrenderentity = (void *)ent;
7936
7937         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7938                 t->camera_entity = ent->entitynumber;
7939         else
7940                 t->camera_entity = 0;
7941
7942         // switch to an alternate material if this is a q1bsp animated material
7943         {
7944                 texture_t *texture = t;
7945                 int s = rsurface.ent_skinnum;
7946                 if ((unsigned int)s >= (unsigned int)model->numskins)
7947                         s = 0;
7948                 if (model->skinscenes)
7949                 {
7950                         if (model->skinscenes[s].framecount > 1)
7951                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7952                         else
7953                                 s = model->skinscenes[s].firstframe;
7954                 }
7955                 if (s > 0)
7956                         t = t + s * model->num_surfaces;
7957                 if (t->animated)
7958                 {
7959                         // use an alternate animation if the entity's frame is not 0,
7960                         // and only if the texture has an alternate animation
7961                         if (t->animated == 2) // q2bsp
7962                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7963                         else if (rsurface.ent_alttextures && t->anim_total[1])
7964                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7965                         else
7966                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7967                 }
7968                 texture->currentframe = t;
7969         }
7970
7971         // update currentskinframe to be a qw skin or animation frame
7972         if (rsurface.ent_qwskin >= 0)
7973         {
7974                 i = rsurface.ent_qwskin;
7975                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7976                 {
7977                         r_qwskincache_size = cl.maxclients;
7978                         if (r_qwskincache)
7979                                 Mem_Free(r_qwskincache);
7980                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7981                 }
7982                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7983                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7984                 t->currentskinframe = r_qwskincache[i].skinframe;
7985                 if (t->materialshaderpass && t->currentskinframe == NULL)
7986                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7987         }
7988         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7989                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7990         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7991                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7992
7993         t->currentmaterialflags = t->basematerialflags;
7994         t->currentalpha = rsurface.entity->alpha * t->basealpha;
7995         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7996                 t->currentalpha *= r_wateralpha.value;
7997         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7998                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7999         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8000                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8001
8002         // decide on which type of lighting to use for this surface
8003         if (rsurface.entity->render_modellight_forced)
8004                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8005         if (rsurface.entity->render_rtlight_disabled)
8006                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8007         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8008         {
8009                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
8010                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8011                 for (q = 0; q < 3; q++)
8012                 {
8013                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8014                         t->render_modellight_lightdir[q] = q == 2;
8015                         t->render_modellight_ambient[q] = 1;
8016                         t->render_modellight_diffuse[q] = 0;
8017                         t->render_modellight_specular[q] = 0;
8018                         t->render_lightmap_ambient[q] = 0;
8019                         t->render_lightmap_diffuse[q] = 0;
8020                         t->render_lightmap_specular[q] = 0;
8021                         t->render_rtlight_diffuse[q] = 0;
8022                         t->render_rtlight_specular[q] = 0;
8023                 }
8024         }
8025         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8026         {
8027                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8028                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8029                 for (q = 0; q < 3; q++)
8030                 {
8031                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8032                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8033                         t->render_modellight_lightdir[q] = q == 2;
8034                         t->render_modellight_diffuse[q] = 0;
8035                         t->render_modellight_specular[q] = 0;
8036                         t->render_lightmap_ambient[q] = 0;
8037                         t->render_lightmap_diffuse[q] = 0;
8038                         t->render_lightmap_specular[q] = 0;
8039                         t->render_rtlight_diffuse[q] = 0;
8040                         t->render_rtlight_specular[q] = 0;
8041                 }
8042         }
8043         else if (FAKELIGHT_ENABLED)
8044         {
8045                 // no modellight if using fakelight for the map
8046                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8047                 for (q = 0; q < 3; q++)
8048                 {
8049                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8050                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8051                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8052                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8053                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8054                         t->render_lightmap_ambient[q] = 0;
8055                         t->render_lightmap_diffuse[q] = 0;
8056                         t->render_lightmap_specular[q] = 0;
8057                         t->render_rtlight_diffuse[q] = 0;
8058                         t->render_rtlight_specular[q] = 0;
8059                 }
8060         }
8061         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8062         {
8063                 // ambient + single direction light (modellight)
8064                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8065                 for (q = 0; q < 3; q++)
8066                 {
8067                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8068                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8069                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8070                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8071                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8072                         t->render_lightmap_ambient[q] = 0;
8073                         t->render_lightmap_diffuse[q] = 0;
8074                         t->render_lightmap_specular[q] = 0;
8075                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8076                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8077                 }
8078         }
8079         else
8080         {
8081                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8082                 for (q = 0; q < 3; q++)
8083                 {
8084                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8085                         t->render_modellight_lightdir[q] = q == 2;
8086                         t->render_modellight_ambient[q] = 0;
8087                         t->render_modellight_diffuse[q] = 0;
8088                         t->render_modellight_specular[q] = 0;
8089                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8090                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8091                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8092                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8093                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8094                 }
8095         }
8096
8097         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8098         {
8099                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8100                 // attribute, we punt it to the lightmap path and hope for the best,
8101                 // but lighting doesn't work.
8102                 //
8103                 // FIXME: this is fine for effects but CSQC polygons should be subject
8104                 // to lighting.
8105                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8106                 for (q = 0; q < 3; q++)
8107                 {
8108                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8109                         t->render_modellight_lightdir[q] = q == 2;
8110                         t->render_modellight_ambient[q] = 0;
8111                         t->render_modellight_diffuse[q] = 0;
8112                         t->render_modellight_specular[q] = 0;
8113                         t->render_lightmap_ambient[q] = 0;
8114                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8115                         t->render_lightmap_specular[q] = 0;
8116                         t->render_rtlight_diffuse[q] = 0;
8117                         t->render_rtlight_specular[q] = 0;
8118                 }
8119         }
8120
8121         for (q = 0; q < 3; q++)
8122         {
8123                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8124                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8125         }
8126
8127         if (rsurface.ent_flags & RENDER_ADDITIVE)
8128                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8129         else if (t->currentalpha < 1)
8130                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8131         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8132         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8133                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8134         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8135                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8136         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8137                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8138         if (t->backgroundshaderpass)
8139                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8140         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8141         {
8142                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8143                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8144         }
8145         else
8146                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8147         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8148         {
8149                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8150                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8151         }
8152         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8153                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8154
8155         // there is no tcmod
8156         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8157         {
8158                 t->currenttexmatrix = r_waterscrollmatrix;
8159                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8160         }
8161         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8162         {
8163                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8164                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8165         }
8166
8167         if (t->materialshaderpass)
8168                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8169                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8170
8171         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8172         if (t->currentskinframe->qpixels)
8173                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8174         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8175         if (!t->basetexture)
8176                 t->basetexture = r_texture_notexture;
8177         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8178         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8179         t->nmaptexture = t->currentskinframe->nmap;
8180         if (!t->nmaptexture)
8181                 t->nmaptexture = r_texture_blanknormalmap;
8182         t->glosstexture = r_texture_black;
8183         t->glowtexture = t->currentskinframe->glow;
8184         t->fogtexture = t->currentskinframe->fog;
8185         t->reflectmasktexture = t->currentskinframe->reflect;
8186         if (t->backgroundshaderpass)
8187         {
8188                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8189                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8190                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8191                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8192                 t->backgroundglosstexture = r_texture_black;
8193                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8194                 if (!t->backgroundnmaptexture)
8195                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8196                 // make sure that if glow is going to be used, both textures are not NULL
8197                 if (!t->backgroundglowtexture && t->glowtexture)
8198                         t->backgroundglowtexture = r_texture_black;
8199                 if (!t->glowtexture && t->backgroundglowtexture)
8200                         t->glowtexture = r_texture_black;
8201         }
8202         else
8203         {
8204                 t->backgroundbasetexture = r_texture_white;
8205                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8206                 t->backgroundglosstexture = r_texture_black;
8207                 t->backgroundglowtexture = NULL;
8208         }
8209         t->specularpower = r_shadow_glossexponent.value;
8210         // TODO: store reference values for these in the texture?
8211         if (r_shadow_gloss.integer > 0)
8212         {
8213                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8214                 {
8215                         if (r_shadow_glossintensity.value > 0)
8216                         {
8217                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8218                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8219                                 specularscale = r_shadow_glossintensity.value;
8220                         }
8221                 }
8222                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8223                 {
8224                         t->glosstexture = r_texture_white;
8225                         t->backgroundglosstexture = r_texture_white;
8226                         specularscale = r_shadow_gloss2intensity.value;
8227                         t->specularpower = r_shadow_gloss2exponent.value;
8228                 }
8229         }
8230         specularscale *= t->specularscalemod;
8231         t->specularpower *= t->specularpowermod;
8232
8233         // lightmaps mode looks bad with dlights using actual texturing, so turn
8234         // off the colormap and glossmap, but leave the normalmap on as it still
8235         // accurately represents the shading involved
8236         if (gl_lightmaps.integer)
8237         {
8238                 t->basetexture = r_texture_grey128;
8239                 t->pantstexture = r_texture_black;
8240                 t->shirttexture = r_texture_black;
8241                 if (gl_lightmaps.integer < 2)
8242                         t->nmaptexture = r_texture_blanknormalmap;
8243                 t->glosstexture = r_texture_black;
8244                 t->glowtexture = NULL;
8245                 t->fogtexture = NULL;
8246                 t->reflectmasktexture = NULL;
8247                 t->backgroundbasetexture = NULL;
8248                 if (gl_lightmaps.integer < 2)
8249                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8250                 t->backgroundglosstexture = r_texture_black;
8251                 t->backgroundglowtexture = NULL;
8252                 specularscale = 0;
8253                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8254         }
8255
8256         if (specularscale != 1.0f)
8257         {
8258                 for (q = 0; q < 3; q++)
8259                 {
8260                         t->render_modellight_specular[q] *= specularscale;
8261                         t->render_lightmap_specular[q] *= specularscale;
8262                         t->render_rtlight_specular[q] *= specularscale;
8263                 }
8264         }
8265
8266         t->currentnumlayers = 0;
8267         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8268         {
8269                 int blendfunc1, blendfunc2;
8270                 qboolean depthmask;
8271                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8272                 {
8273                         blendfunc1 = GL_SRC_ALPHA;
8274                         blendfunc2 = GL_ONE;
8275                 }
8276                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8277                 {
8278                         blendfunc1 = GL_SRC_ALPHA;
8279                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8280                 }
8281                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8282                 {
8283                         blendfunc1 = t->customblendfunc[0];
8284                         blendfunc2 = t->customblendfunc[1];
8285                 }
8286                 else
8287                 {
8288                         blendfunc1 = GL_ONE;
8289                         blendfunc2 = GL_ZERO;
8290                 }
8291                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8292                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8293                 {
8294                         // basic lit geometry
8295                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
8296                         // add pants/shirt if needed
8297                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8298                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, 2 * t->render_colormap_pants[0], 2 * t->render_colormap_pants[1], 2 * t->render_colormap_pants[2], t->currentalpha);
8299                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8300                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, 2 * t->render_colormap_shirt[0], 2 * t->render_colormap_shirt[1], 2 * t->render_colormap_shirt[2], t->currentalpha);
8301                 }
8302                 else
8303                 {
8304                         // basic lit geometry
8305                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8306                         // add pants/shirt if needed
8307                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8308                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8309                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8310                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8311                         // now add ambient passes if needed
8312                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8313                         {
8314                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8315                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8316                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8317                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8318                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8319                         }
8320                 }
8321                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8322                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8323                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8324                 {
8325                         // if this is opaque use alpha blend which will darken the earlier
8326                         // passes cheaply.
8327                         //
8328                         // if this is an alpha blended material, all the earlier passes
8329                         // were darkened by fog already, so we only need to add the fog
8330                         // color ontop through the fog mask texture
8331                         //
8332                         // if this is an additive blended material, all the earlier passes
8333                         // were darkened by fog already, and we should not add fog color
8334                         // (because the background was not darkened, there is no fog color
8335                         // that was lost behind it).
8336                         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->currentalpha);
8337                 }
8338         }
8339
8340         return t;
8341 }
8342
8343 rsurfacestate_t rsurface;
8344
8345 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8346 {
8347         dp_model_t *model = ent->model;
8348         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8349         //      return;
8350         rsurface.entity = (entity_render_t *)ent;
8351         rsurface.skeleton = ent->skeleton;
8352         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8353         rsurface.ent_skinnum = ent->skinnum;
8354         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;
8355         rsurface.ent_flags = ent->flags;
8356         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8357                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8358         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8359         rsurface.matrix = ent->matrix;
8360         rsurface.inversematrix = ent->inversematrix;
8361         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8362         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8363         R_EntityMatrix(&rsurface.matrix);
8364         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8365         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8366         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8367         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8368         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8369         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8370         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8371         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8372         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8373         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8374         if (ent->model->brush.submodel && !prepass)
8375         {
8376                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8377                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8378         }
8379         // if the animcache code decided it should use the shader path, skip the deform step
8380         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8381         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8382         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8383         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8384         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8385         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8386         {
8387                 if (ent->animcache_vertex3f)
8388                 {
8389                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8390                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8391                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8392                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8393                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8394                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8395                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8396                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8397                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8398                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8399                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8400                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8401                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8402                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8403                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8404                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8405                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8406                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8407                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8408                 }
8409                 else if (wanttangents)
8410                 {
8411                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8412                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8413                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8414                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8415                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8417                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8418                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8419                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8420                         rsurface.modelvertexmesh = NULL;
8421                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8422                         rsurface.modelvertexmesh_bufferoffset = 0;
8423                         rsurface.modelvertex3f_vertexbuffer = NULL;
8424                         rsurface.modelvertex3f_bufferoffset = 0;
8425                         rsurface.modelvertex3f_vertexbuffer = 0;
8426                         rsurface.modelvertex3f_bufferoffset = 0;
8427                         rsurface.modelsvector3f_vertexbuffer = 0;
8428                         rsurface.modelsvector3f_bufferoffset = 0;
8429                         rsurface.modeltvector3f_vertexbuffer = 0;
8430                         rsurface.modeltvector3f_bufferoffset = 0;
8431                         rsurface.modelnormal3f_vertexbuffer = 0;
8432                         rsurface.modelnormal3f_bufferoffset = 0;
8433                 }
8434                 else if (wantnormals)
8435                 {
8436                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8437                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8438                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8439                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8440                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8441                         rsurface.modelsvector3f = NULL;
8442                         rsurface.modeltvector3f = NULL;
8443                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8444                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8445                         rsurface.modelvertexmesh = NULL;
8446                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8447                         rsurface.modelvertexmesh_bufferoffset = 0;
8448                         rsurface.modelvertex3f_vertexbuffer = NULL;
8449                         rsurface.modelvertex3f_bufferoffset = 0;
8450                         rsurface.modelvertex3f_vertexbuffer = 0;
8451                         rsurface.modelvertex3f_bufferoffset = 0;
8452                         rsurface.modelsvector3f_vertexbuffer = 0;
8453                         rsurface.modelsvector3f_bufferoffset = 0;
8454                         rsurface.modeltvector3f_vertexbuffer = 0;
8455                         rsurface.modeltvector3f_bufferoffset = 0;
8456                         rsurface.modelnormal3f_vertexbuffer = 0;
8457                         rsurface.modelnormal3f_bufferoffset = 0;
8458                 }
8459                 else
8460                 {
8461                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8462                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8463                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8464                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8465                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8466                         rsurface.modelsvector3f = NULL;
8467                         rsurface.modeltvector3f = NULL;
8468                         rsurface.modelnormal3f = NULL;
8469                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8470                         rsurface.modelvertexmesh = NULL;
8471                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8472                         rsurface.modelvertexmesh_bufferoffset = 0;
8473                         rsurface.modelvertex3f_vertexbuffer = NULL;
8474                         rsurface.modelvertex3f_bufferoffset = 0;
8475                         rsurface.modelvertex3f_vertexbuffer = 0;
8476                         rsurface.modelvertex3f_bufferoffset = 0;
8477                         rsurface.modelsvector3f_vertexbuffer = 0;
8478                         rsurface.modelsvector3f_bufferoffset = 0;
8479                         rsurface.modeltvector3f_vertexbuffer = 0;
8480                         rsurface.modeltvector3f_bufferoffset = 0;
8481                         rsurface.modelnormal3f_vertexbuffer = 0;
8482                         rsurface.modelnormal3f_bufferoffset = 0;
8483                 }
8484                 rsurface.modelgeneratedvertex = true;
8485         }
8486         else
8487         {
8488                 if (rsurface.entityskeletaltransform3x4)
8489                 {
8490                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8491                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8492                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8493                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8494                 }
8495                 else
8496                 {
8497                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8498                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8499                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8500                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8501                 }
8502                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8503                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8504                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8505                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8506                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8507                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8508                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8509                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8510                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8511                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8512                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8513                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8514                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8515                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8516                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8517                 rsurface.modelgeneratedvertex = false;
8518         }
8519         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8520         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8521         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8522         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8523         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8524         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8525         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8526         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8527         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8528         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8529         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8531         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8532         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8534         rsurface.modelelement3i = model->surfmesh.data_element3i;
8535         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8536         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8537         rsurface.modelelement3s = model->surfmesh.data_element3s;
8538         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8539         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8540         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8541         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8542         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8543         rsurface.modelsurfaces = model->data_surfaces;
8544         rsurface.batchgeneratedvertex = false;
8545         rsurface.batchfirstvertex = 0;
8546         rsurface.batchnumvertices = 0;
8547         rsurface.batchfirsttriangle = 0;
8548         rsurface.batchnumtriangles = 0;
8549         rsurface.batchvertex3f  = NULL;
8550         rsurface.batchvertex3f_vertexbuffer = NULL;
8551         rsurface.batchvertex3f_bufferoffset = 0;
8552         rsurface.batchsvector3f = NULL;
8553         rsurface.batchsvector3f_vertexbuffer = NULL;
8554         rsurface.batchsvector3f_bufferoffset = 0;
8555         rsurface.batchtvector3f = NULL;
8556         rsurface.batchtvector3f_vertexbuffer = NULL;
8557         rsurface.batchtvector3f_bufferoffset = 0;
8558         rsurface.batchnormal3f  = NULL;
8559         rsurface.batchnormal3f_vertexbuffer = NULL;
8560         rsurface.batchnormal3f_bufferoffset = 0;
8561         rsurface.batchlightmapcolor4f = NULL;
8562         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8563         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8564         rsurface.batchtexcoordtexture2f = NULL;
8565         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8566         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8567         rsurface.batchtexcoordlightmap2f = NULL;
8568         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8569         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8570         rsurface.batchskeletalindex4ub = NULL;
8571         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8572         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8573         rsurface.batchskeletalweight4ub = NULL;
8574         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8575         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8576         rsurface.batchvertexmesh = NULL;
8577         rsurface.batchvertexmesh_vertexbuffer = NULL;
8578         rsurface.batchvertexmesh_bufferoffset = 0;
8579         rsurface.batchelement3i = NULL;
8580         rsurface.batchelement3i_indexbuffer = NULL;
8581         rsurface.batchelement3i_bufferoffset = 0;
8582         rsurface.batchelement3s = NULL;
8583         rsurface.batchelement3s_indexbuffer = NULL;
8584         rsurface.batchelement3s_bufferoffset = 0;
8585         rsurface.passcolor4f = NULL;
8586         rsurface.passcolor4f_vertexbuffer = NULL;
8587         rsurface.passcolor4f_bufferoffset = 0;
8588         rsurface.forcecurrenttextureupdate = false;
8589 }
8590
8591 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)
8592 {
8593         rsurface.entity = r_refdef.scene.worldentity;
8594         rsurface.skeleton = NULL;
8595         rsurface.ent_skinnum = 0;
8596         rsurface.ent_qwskin = -1;
8597         rsurface.ent_flags = entflags;
8598         rsurface.shadertime = r_refdef.scene.time - shadertime;
8599         rsurface.modelnumvertices = numvertices;
8600         rsurface.modelnumtriangles = numtriangles;
8601         rsurface.matrix = *matrix;
8602         rsurface.inversematrix = *inversematrix;
8603         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8604         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8605         R_EntityMatrix(&rsurface.matrix);
8606         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8607         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8608         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8609         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8610         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8611         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8612         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8613         rsurface.frameblend[0].lerp = 1;
8614         rsurface.ent_alttextures = false;
8615         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8616         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8617         rsurface.entityskeletaltransform3x4 = NULL;
8618         rsurface.entityskeletaltransform3x4buffer = NULL;
8619         rsurface.entityskeletaltransform3x4offset = 0;
8620         rsurface.entityskeletaltransform3x4size = 0;
8621         rsurface.entityskeletalnumtransforms = 0;
8622         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8623         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8624         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8625         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8626         if (wanttangents)
8627         {
8628                 rsurface.modelvertex3f = (float *)vertex3f;
8629                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8630                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8631                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8632         }
8633         else if (wantnormals)
8634         {
8635                 rsurface.modelvertex3f = (float *)vertex3f;
8636                 rsurface.modelsvector3f = NULL;
8637                 rsurface.modeltvector3f = NULL;
8638                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8639         }
8640         else
8641         {
8642                 rsurface.modelvertex3f = (float *)vertex3f;
8643                 rsurface.modelsvector3f = NULL;
8644                 rsurface.modeltvector3f = NULL;
8645                 rsurface.modelnormal3f = NULL;
8646         }
8647         rsurface.modelvertexmesh = NULL;
8648         rsurface.modelvertexmesh_vertexbuffer = NULL;
8649         rsurface.modelvertexmesh_bufferoffset = 0;
8650         rsurface.modelvertex3f_vertexbuffer = 0;
8651         rsurface.modelvertex3f_bufferoffset = 0;
8652         rsurface.modelsvector3f_vertexbuffer = 0;
8653         rsurface.modelsvector3f_bufferoffset = 0;
8654         rsurface.modeltvector3f_vertexbuffer = 0;
8655         rsurface.modeltvector3f_bufferoffset = 0;
8656         rsurface.modelnormal3f_vertexbuffer = 0;
8657         rsurface.modelnormal3f_bufferoffset = 0;
8658         rsurface.modelgeneratedvertex = true;
8659         rsurface.modellightmapcolor4f  = (float *)color4f;
8660         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8661         rsurface.modellightmapcolor4f_bufferoffset = 0;
8662         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8663         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8664         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8665         rsurface.modeltexcoordlightmap2f  = NULL;
8666         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8667         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8668         rsurface.modelskeletalindex4ub = NULL;
8669         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8670         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8671         rsurface.modelskeletalweight4ub = NULL;
8672         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8673         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8674         rsurface.modelelement3i = (int *)element3i;
8675         rsurface.modelelement3i_indexbuffer = NULL;
8676         rsurface.modelelement3i_bufferoffset = 0;
8677         rsurface.modelelement3s = (unsigned short *)element3s;
8678         rsurface.modelelement3s_indexbuffer = NULL;
8679         rsurface.modelelement3s_bufferoffset = 0;
8680         rsurface.modellightmapoffsets = NULL;
8681         rsurface.modelsurfaces = NULL;
8682         rsurface.batchgeneratedvertex = false;
8683         rsurface.batchfirstvertex = 0;
8684         rsurface.batchnumvertices = 0;
8685         rsurface.batchfirsttriangle = 0;
8686         rsurface.batchnumtriangles = 0;
8687         rsurface.batchvertex3f  = NULL;
8688         rsurface.batchvertex3f_vertexbuffer = NULL;
8689         rsurface.batchvertex3f_bufferoffset = 0;
8690         rsurface.batchsvector3f = NULL;
8691         rsurface.batchsvector3f_vertexbuffer = NULL;
8692         rsurface.batchsvector3f_bufferoffset = 0;
8693         rsurface.batchtvector3f = NULL;
8694         rsurface.batchtvector3f_vertexbuffer = NULL;
8695         rsurface.batchtvector3f_bufferoffset = 0;
8696         rsurface.batchnormal3f  = NULL;
8697         rsurface.batchnormal3f_vertexbuffer = NULL;
8698         rsurface.batchnormal3f_bufferoffset = 0;
8699         rsurface.batchlightmapcolor4f = NULL;
8700         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8701         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8702         rsurface.batchtexcoordtexture2f = NULL;
8703         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8704         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8705         rsurface.batchtexcoordlightmap2f = NULL;
8706         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8707         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8708         rsurface.batchskeletalindex4ub = NULL;
8709         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8710         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8711         rsurface.batchskeletalweight4ub = NULL;
8712         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8713         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8714         rsurface.batchvertexmesh = NULL;
8715         rsurface.batchvertexmesh_vertexbuffer = NULL;
8716         rsurface.batchvertexmesh_bufferoffset = 0;
8717         rsurface.batchelement3i = NULL;
8718         rsurface.batchelement3i_indexbuffer = NULL;
8719         rsurface.batchelement3i_bufferoffset = 0;
8720         rsurface.batchelement3s = NULL;
8721         rsurface.batchelement3s_indexbuffer = NULL;
8722         rsurface.batchelement3s_bufferoffset = 0;
8723         rsurface.passcolor4f = NULL;
8724         rsurface.passcolor4f_vertexbuffer = NULL;
8725         rsurface.passcolor4f_bufferoffset = 0;
8726         rsurface.forcecurrenttextureupdate = true;
8727
8728         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8729         {
8730                 if ((wantnormals || wanttangents) && !normal3f)
8731                 {
8732                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8733                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8734                 }
8735                 if (wanttangents && !svector3f)
8736                 {
8737                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8738                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8739                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8740                 }
8741         }
8742 }
8743
8744 float RSurf_FogPoint(const float *v)
8745 {
8746         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8747         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8748         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8749         float FogHeightFade = r_refdef.fogheightfade;
8750         float fogfrac;
8751         unsigned int fogmasktableindex;
8752         if (r_refdef.fogplaneviewabove)
8753                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8754         else
8755                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8756         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8757         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8758 }
8759
8760 float RSurf_FogVertex(const float *v)
8761 {
8762         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8763         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8764         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8765         float FogHeightFade = rsurface.fogheightfade;
8766         float fogfrac;
8767         unsigned int fogmasktableindex;
8768         if (r_refdef.fogplaneviewabove)
8769                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8770         else
8771                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8772         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8773         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8774 }
8775
8776 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8777 {
8778         int i;
8779         for (i = 0;i < numelements;i++)
8780                 outelement3i[i] = inelement3i[i] + adjust;
8781 }
8782
8783 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8784 extern cvar_t gl_vbo;
8785 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8786 {
8787         int deformindex;
8788         int firsttriangle;
8789         int numtriangles;
8790         int firstvertex;
8791         int endvertex;
8792         int numvertices;
8793         int surfacefirsttriangle;
8794         int surfacenumtriangles;
8795         int surfacefirstvertex;
8796         int surfaceendvertex;
8797         int surfacenumvertices;
8798         int batchnumsurfaces = texturenumsurfaces;
8799         int batchnumvertices;
8800         int batchnumtriangles;
8801         int needsupdate;
8802         int i, j;
8803         qboolean gaps;
8804         qboolean dynamicvertex;
8805         float amplitude;
8806         float animpos;
8807         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8808         float waveparms[4];
8809         unsigned char *ub;
8810         q3shaderinfo_deform_t *deform;
8811         const msurface_t *surface, *firstsurface;
8812         r_vertexmesh_t *vertexmesh;
8813         if (!texturenumsurfaces)
8814                 return;
8815         // find vertex range of this surface batch
8816         gaps = false;
8817         firstsurface = texturesurfacelist[0];
8818         firsttriangle = firstsurface->num_firsttriangle;
8819         batchnumvertices = 0;
8820         batchnumtriangles = 0;
8821         firstvertex = endvertex = firstsurface->num_firstvertex;
8822         for (i = 0;i < texturenumsurfaces;i++)
8823         {
8824                 surface = texturesurfacelist[i];
8825                 if (surface != firstsurface + i)
8826                         gaps = true;
8827                 surfacefirstvertex = surface->num_firstvertex;
8828                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8829                 surfacenumvertices = surface->num_vertices;
8830                 surfacenumtriangles = surface->num_triangles;
8831                 if (firstvertex > surfacefirstvertex)
8832                         firstvertex = surfacefirstvertex;
8833                 if (endvertex < surfaceendvertex)
8834                         endvertex = surfaceendvertex;
8835                 batchnumvertices += surfacenumvertices;
8836                 batchnumtriangles += surfacenumtriangles;
8837         }
8838
8839         r_refdef.stats[r_stat_batch_batches]++;
8840         if (gaps)
8841                 r_refdef.stats[r_stat_batch_withgaps]++;
8842         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8843         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8844         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8845
8846         // we now know the vertex range used, and if there are any gaps in it
8847         rsurface.batchfirstvertex = firstvertex;
8848         rsurface.batchnumvertices = endvertex - firstvertex;
8849         rsurface.batchfirsttriangle = firsttriangle;
8850         rsurface.batchnumtriangles = batchnumtriangles;
8851
8852         // this variable holds flags for which properties have been updated that
8853         // may require regenerating vertexmesh array...
8854         needsupdate = 0;
8855
8856         // check if any dynamic vertex processing must occur
8857         dynamicvertex = false;
8858
8859         // a cvar to force the dynamic vertex path to be taken, for debugging
8860         if (r_batch_debugdynamicvertexpath.integer)
8861         {
8862                 if (!dynamicvertex)
8863                 {
8864                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8865                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8866                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8867                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8868                 }
8869                 dynamicvertex = true;
8870         }
8871
8872         // if there is a chance of animated vertex colors, it's a dynamic batch
8873         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8874         {
8875                 if (!dynamicvertex)
8876                 {
8877                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8878                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8879                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8880                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8881                 }
8882                 dynamicvertex = true;
8883                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8884         }
8885
8886         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8887         {
8888                 switch (deform->deform)
8889                 {
8890                 default:
8891                 case Q3DEFORM_PROJECTIONSHADOW:
8892                 case Q3DEFORM_TEXT0:
8893                 case Q3DEFORM_TEXT1:
8894                 case Q3DEFORM_TEXT2:
8895                 case Q3DEFORM_TEXT3:
8896                 case Q3DEFORM_TEXT4:
8897                 case Q3DEFORM_TEXT5:
8898                 case Q3DEFORM_TEXT6:
8899                 case Q3DEFORM_TEXT7:
8900                 case Q3DEFORM_NONE:
8901                         break;
8902                 case Q3DEFORM_AUTOSPRITE:
8903                         if (!dynamicvertex)
8904                         {
8905                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8906                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8907                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8908                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8909                         }
8910                         dynamicvertex = true;
8911                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8912                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8913                         break;
8914                 case Q3DEFORM_AUTOSPRITE2:
8915                         if (!dynamicvertex)
8916                         {
8917                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8918                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8919                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8920                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8921                         }
8922                         dynamicvertex = true;
8923                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8924                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8925                         break;
8926                 case Q3DEFORM_NORMAL:
8927                         if (!dynamicvertex)
8928                         {
8929                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8930                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8931                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8932                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8933                         }
8934                         dynamicvertex = true;
8935                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8936                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8937                         break;
8938                 case Q3DEFORM_WAVE:
8939                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8940                                 break; // if wavefunc is a nop, ignore this transform
8941                         if (!dynamicvertex)
8942                         {
8943                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8944                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8945                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8946                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8947                         }
8948                         dynamicvertex = true;
8949                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8950                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8951                         break;
8952                 case Q3DEFORM_BULGE:
8953                         if (!dynamicvertex)
8954                         {
8955                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8956                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8957                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8958                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8959                         }
8960                         dynamicvertex = true;
8961                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8962                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8963                         break;
8964                 case Q3DEFORM_MOVE:
8965                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8966                                 break; // if wavefunc is a nop, ignore this transform
8967                         if (!dynamicvertex)
8968                         {
8969                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8970                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8971                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8972                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8973                         }
8974                         dynamicvertex = true;
8975                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8976                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8977                         break;
8978                 }
8979         }
8980         if (rsurface.texture->materialshaderpass)
8981         {
8982                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8983                 {
8984                 default:
8985                 case Q3TCGEN_TEXTURE:
8986                         break;
8987                 case Q3TCGEN_LIGHTMAP:
8988                         if (!dynamicvertex)
8989                         {
8990                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8991                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8992                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8993                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8994                         }
8995                         dynamicvertex = true;
8996                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8997                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8998                         break;
8999                 case Q3TCGEN_VECTOR:
9000                         if (!dynamicvertex)
9001                         {
9002                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9003                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9004                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9005                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9006                         }
9007                         dynamicvertex = true;
9008                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9009                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9010                         break;
9011                 case Q3TCGEN_ENVIRONMENT:
9012                         if (!dynamicvertex)
9013                         {
9014                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9015                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9016                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9017                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9018                         }
9019                         dynamicvertex = true;
9020                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9021                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9022                         break;
9023                 }
9024                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9025                 {
9026                         if (!dynamicvertex)
9027                         {
9028                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9029                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9030                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9031                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9032                         }
9033                         dynamicvertex = true;
9034                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9035                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9036                 }
9037         }
9038
9039         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9040         {
9041                 if (!dynamicvertex)
9042                 {
9043                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9044                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9045                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9046                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9047                 }
9048                 dynamicvertex = true;
9049                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9050         }
9051
9052         // when the model data has no vertex buffer (dynamic mesh), we need to
9053         // eliminate gaps
9054         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9055                 batchneed |= BATCHNEED_NOGAPS;
9056
9057         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9058         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9059         // we ensure this by treating the vertex batch as dynamic...
9060         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9061         {
9062                 if (!dynamicvertex)
9063                 {
9064                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9065                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9066                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9067                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9068                 }
9069                 dynamicvertex = true;
9070         }
9071
9072         if (dynamicvertex)
9073         {
9074                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9075                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9076                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9077                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9078                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9079                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9080                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9081                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9082         }
9083
9084         // if needsupdate, we have to do a dynamic vertex batch for sure
9085         if (needsupdate & batchneed)
9086         {
9087                 if (!dynamicvertex)
9088                 {
9089                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9090                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9091                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9092                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9093                 }
9094                 dynamicvertex = true;
9095         }
9096
9097         // see if we need to build vertexmesh from arrays
9098         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9099         {
9100                 if (!dynamicvertex)
9101                 {
9102                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9103                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9104                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9105                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9106                 }
9107                 dynamicvertex = true;
9108         }
9109
9110         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9111         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9112                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9113
9114         rsurface.batchvertex3f = rsurface.modelvertex3f;
9115         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9116         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9117         rsurface.batchsvector3f = rsurface.modelsvector3f;
9118         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9119         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9120         rsurface.batchtvector3f = rsurface.modeltvector3f;
9121         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9122         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9123         rsurface.batchnormal3f = rsurface.modelnormal3f;
9124         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9125         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9126         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9127         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9128         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9129         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9130         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9131         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9132         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9133         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9134         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9135         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9136         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9137         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9138         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9139         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9140         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9141         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9142         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9143         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9144         rsurface.batchelement3i = rsurface.modelelement3i;
9145         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9146         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9147         rsurface.batchelement3s = rsurface.modelelement3s;
9148         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9149         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9150         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9151         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9152         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9153         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9154         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9155
9156         // if any dynamic vertex processing has to occur in software, we copy the
9157         // entire surface list together before processing to rebase the vertices
9158         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9159         //
9160         // if any gaps exist and we do not have a static vertex buffer, we have to
9161         // copy the surface list together to avoid wasting upload bandwidth on the
9162         // vertices in the gaps.
9163         //
9164         // if gaps exist and we have a static vertex buffer, we can choose whether
9165         // to combine the index buffer ranges into one dynamic index buffer or
9166         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9167         //
9168         // in many cases the batch is reduced to one draw call.
9169
9170         rsurface.batchmultidraw = false;
9171         rsurface.batchmultidrawnumsurfaces = 0;
9172         rsurface.batchmultidrawsurfacelist = NULL;
9173
9174         if (!dynamicvertex)
9175         {
9176                 // static vertex data, just set pointers...
9177                 rsurface.batchgeneratedvertex = false;
9178                 // if there are gaps, we want to build a combined index buffer,
9179                 // otherwise use the original static buffer with an appropriate offset
9180                 if (gaps)
9181                 {
9182                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9183                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9184                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9185                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9186                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9187                         {
9188                                 rsurface.batchmultidraw = true;
9189                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9190                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9191                                 return;
9192                         }
9193                         // build a new triangle elements array for this batch
9194                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9195                         rsurface.batchfirsttriangle = 0;
9196                         numtriangles = 0;
9197                         for (i = 0;i < texturenumsurfaces;i++)
9198                         {
9199                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9200                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9201                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9202                                 numtriangles += surfacenumtriangles;
9203                         }
9204                         rsurface.batchelement3i_indexbuffer = NULL;
9205                         rsurface.batchelement3i_bufferoffset = 0;
9206                         rsurface.batchelement3s = NULL;
9207                         rsurface.batchelement3s_indexbuffer = NULL;
9208                         rsurface.batchelement3s_bufferoffset = 0;
9209                         if (endvertex <= 65536)
9210                         {
9211                                 // make a 16bit (unsigned short) index array if possible
9212                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9213                                 for (i = 0;i < numtriangles*3;i++)
9214                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9215                         }
9216                         // upload buffer data for the copytriangles batch
9217                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9218                         {
9219                                 if (rsurface.batchelement3s)
9220                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9221                                 else if (rsurface.batchelement3i)
9222                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9223                         }
9224                 }
9225                 else
9226                 {
9227                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9228                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9229                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9230                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9231                 }
9232                 return;
9233         }
9234
9235         // something needs software processing, do it for real...
9236         // we only directly handle separate array data in this case and then
9237         // generate interleaved data if needed...
9238         rsurface.batchgeneratedvertex = true;
9239         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9240         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9241         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9242         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9243
9244         // now copy the vertex data into a combined array and make an index array
9245         // (this is what Quake3 does all the time)
9246         // we also apply any skeletal animation here that would have been done in
9247         // the vertex shader, because most of the dynamic vertex animation cases
9248         // need actual vertex positions and normals
9249         //if (dynamicvertex)
9250         {
9251                 rsurface.batchvertexmesh = NULL;
9252                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9253                 rsurface.batchvertexmesh_bufferoffset = 0;
9254                 rsurface.batchvertex3f = NULL;
9255                 rsurface.batchvertex3f_vertexbuffer = NULL;
9256                 rsurface.batchvertex3f_bufferoffset = 0;
9257                 rsurface.batchsvector3f = NULL;
9258                 rsurface.batchsvector3f_vertexbuffer = NULL;
9259                 rsurface.batchsvector3f_bufferoffset = 0;
9260                 rsurface.batchtvector3f = NULL;
9261                 rsurface.batchtvector3f_vertexbuffer = NULL;
9262                 rsurface.batchtvector3f_bufferoffset = 0;
9263                 rsurface.batchnormal3f = NULL;
9264                 rsurface.batchnormal3f_vertexbuffer = NULL;
9265                 rsurface.batchnormal3f_bufferoffset = 0;
9266                 rsurface.batchlightmapcolor4f = NULL;
9267                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9268                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9269                 rsurface.batchtexcoordtexture2f = NULL;
9270                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9271                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9272                 rsurface.batchtexcoordlightmap2f = NULL;
9273                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9274                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9275                 rsurface.batchskeletalindex4ub = NULL;
9276                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9277                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9278                 rsurface.batchskeletalweight4ub = NULL;
9279                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9280                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9281                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9282                 rsurface.batchelement3i_indexbuffer = NULL;
9283                 rsurface.batchelement3i_bufferoffset = 0;
9284                 rsurface.batchelement3s = NULL;
9285                 rsurface.batchelement3s_indexbuffer = NULL;
9286                 rsurface.batchelement3s_bufferoffset = 0;
9287                 rsurface.batchskeletaltransform3x4buffer = NULL;
9288                 rsurface.batchskeletaltransform3x4offset = 0;
9289                 rsurface.batchskeletaltransform3x4size = 0;
9290                 // we'll only be setting up certain arrays as needed
9291                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9292                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9293                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9294                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9295                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9296                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9297                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9298                 {
9299                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9300                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9301                 }
9302                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9303                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9304                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9305                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9306                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9307                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9308                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9309                 {
9310                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9311                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9312                 }
9313                 numvertices = 0;
9314                 numtriangles = 0;
9315                 for (i = 0;i < texturenumsurfaces;i++)
9316                 {
9317                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9318                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9319                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9320                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9321                         // copy only the data requested
9322                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9323                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9324                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9325                         {
9326                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9327                                 {
9328                                         if (rsurface.batchvertex3f)
9329                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9330                                         else
9331                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9332                                 }
9333                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9334                                 {
9335                                         if (rsurface.modelnormal3f)
9336                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9337                                         else
9338                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9339                                 }
9340                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9341                                 {
9342                                         if (rsurface.modelsvector3f)
9343                                         {
9344                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9345                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9346                                         }
9347                                         else
9348                                         {
9349                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9350                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9351                                         }
9352                                 }
9353                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9354                                 {
9355                                         if (rsurface.modellightmapcolor4f)
9356                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9357                                         else
9358                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9359                                 }
9360                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9361                                 {
9362                                         if (rsurface.modeltexcoordtexture2f)
9363                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9364                                         else
9365                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9366                                 }
9367                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9368                                 {
9369                                         if (rsurface.modeltexcoordlightmap2f)
9370                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9371                                         else
9372                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9373                                 }
9374                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9375                                 {
9376                                         if (rsurface.modelskeletalindex4ub)
9377                                         {
9378                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9379                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9380                                         }
9381                                         else
9382                                         {
9383                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9384                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9385                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9386                                                 for (j = 0;j < surfacenumvertices;j++)
9387                                                         ub[j*4] = 255;
9388                                         }
9389                                 }
9390                         }
9391                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9392                         numvertices += surfacenumvertices;
9393                         numtriangles += surfacenumtriangles;
9394                 }
9395
9396                 // generate a 16bit index array as well if possible
9397                 // (in general, dynamic batches fit)
9398                 if (numvertices <= 65536)
9399                 {
9400                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9401                         for (i = 0;i < numtriangles*3;i++)
9402                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9403                 }
9404
9405                 // since we've copied everything, the batch now starts at 0
9406                 rsurface.batchfirstvertex = 0;
9407                 rsurface.batchnumvertices = batchnumvertices;
9408                 rsurface.batchfirsttriangle = 0;
9409                 rsurface.batchnumtriangles = batchnumtriangles;
9410         }
9411
9412         // apply skeletal animation that would have been done in the vertex shader
9413         if (rsurface.batchskeletaltransform3x4)
9414         {
9415                 const unsigned char *si;
9416                 const unsigned char *sw;
9417                 const float *t[4];
9418                 const float *b = rsurface.batchskeletaltransform3x4;
9419                 float *vp, *vs, *vt, *vn;
9420                 float w[4];
9421                 float m[3][4], n[3][4];
9422                 float tp[3], ts[3], tt[3], tn[3];
9423                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9424                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9425                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9426                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9427                 si = rsurface.batchskeletalindex4ub;
9428                 sw = rsurface.batchskeletalweight4ub;
9429                 vp = rsurface.batchvertex3f;
9430                 vs = rsurface.batchsvector3f;
9431                 vt = rsurface.batchtvector3f;
9432                 vn = rsurface.batchnormal3f;
9433                 memset(m[0], 0, sizeof(m));
9434                 memset(n[0], 0, sizeof(n));
9435                 for (i = 0;i < batchnumvertices;i++)
9436                 {
9437                         t[0] = b + si[0]*12;
9438                         if (sw[0] == 255)
9439                         {
9440                                 // common case - only one matrix
9441                                 m[0][0] = t[0][ 0];
9442                                 m[0][1] = t[0][ 1];
9443                                 m[0][2] = t[0][ 2];
9444                                 m[0][3] = t[0][ 3];
9445                                 m[1][0] = t[0][ 4];
9446                                 m[1][1] = t[0][ 5];
9447                                 m[1][2] = t[0][ 6];
9448                                 m[1][3] = t[0][ 7];
9449                                 m[2][0] = t[0][ 8];
9450                                 m[2][1] = t[0][ 9];
9451                                 m[2][2] = t[0][10];
9452                                 m[2][3] = t[0][11];
9453                         }
9454                         else if (sw[2] + sw[3])
9455                         {
9456                                 // blend 4 matrices
9457                                 t[1] = b + si[1]*12;
9458                                 t[2] = b + si[2]*12;
9459                                 t[3] = b + si[3]*12;
9460                                 w[0] = sw[0] * (1.0f / 255.0f);
9461                                 w[1] = sw[1] * (1.0f / 255.0f);
9462                                 w[2] = sw[2] * (1.0f / 255.0f);
9463                                 w[3] = sw[3] * (1.0f / 255.0f);
9464                                 // blend the matrices
9465                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9466                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9467                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9468                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9469                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9470                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9471                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9472                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9473                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9474                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9475                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9476                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9477                         }
9478                         else
9479                         {
9480                                 // blend 2 matrices
9481                                 t[1] = b + si[1]*12;
9482                                 w[0] = sw[0] * (1.0f / 255.0f);
9483                                 w[1] = sw[1] * (1.0f / 255.0f);
9484                                 // blend the matrices
9485                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9486                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9487                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9488                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9489                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9490                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9491                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9492                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9493                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9494                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9495                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9496                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9497                         }
9498                         si += 4;
9499                         sw += 4;
9500                         // modify the vertex
9501                         VectorCopy(vp, tp);
9502                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9503                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9504                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9505                         vp += 3;
9506                         if (vn)
9507                         {
9508                                 // the normal transformation matrix is a set of cross products...
9509                                 CrossProduct(m[1], m[2], n[0]);
9510                                 CrossProduct(m[2], m[0], n[1]);
9511                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9512                                 VectorCopy(vn, tn);
9513                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9514                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9515                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9516                                 VectorNormalize(vn);
9517                                 vn += 3;
9518                                 if (vs)
9519                                 {
9520                                         VectorCopy(vs, ts);
9521                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9522                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9523                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9524                                         VectorNormalize(vs);
9525                                         vs += 3;
9526                                         VectorCopy(vt, tt);
9527                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9528                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9529                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9530                                         VectorNormalize(vt);
9531                                         vt += 3;
9532                                 }
9533                         }
9534                 }
9535                 rsurface.batchskeletaltransform3x4 = NULL;
9536                 rsurface.batchskeletalnumtransforms = 0;
9537         }
9538
9539         // q1bsp surfaces rendered in vertex color mode have to have colors
9540         // calculated based on lightstyles
9541         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9542         {
9543                 // generate color arrays for the surfaces in this list
9544                 int c[4];
9545                 int scale;
9546                 int size3;
9547                 const int *offsets;
9548                 const unsigned char *lm;
9549                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9550                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9551                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9552                 numvertices = 0;
9553                 for (i = 0;i < texturenumsurfaces;i++)
9554                 {
9555                         surface = texturesurfacelist[i];
9556                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9557                         surfacenumvertices = surface->num_vertices;
9558                         if (surface->lightmapinfo->samples)
9559                         {
9560                                 for (j = 0;j < surfacenumvertices;j++)
9561                                 {
9562                                         lm = surface->lightmapinfo->samples + offsets[j];
9563                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9564                                         VectorScale(lm, scale, c);
9565                                         if (surface->lightmapinfo->styles[1] != 255)
9566                                         {
9567                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9568                                                 lm += size3;
9569                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9570                                                 VectorMA(c, scale, lm, c);
9571                                                 if (surface->lightmapinfo->styles[2] != 255)
9572                                                 {
9573                                                         lm += size3;
9574                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9575                                                         VectorMA(c, scale, lm, c);
9576                                                         if (surface->lightmapinfo->styles[3] != 255)
9577                                                         {
9578                                                                 lm += size3;
9579                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9580                                                                 VectorMA(c, scale, lm, c);
9581                                                         }
9582                                                 }
9583                                         }
9584                                         c[0] >>= 7;
9585                                         c[1] >>= 7;
9586                                         c[2] >>= 7;
9587                                         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);
9588                                         numvertices++;
9589                                 }
9590                         }
9591                         else
9592                         {
9593                                 for (j = 0;j < surfacenumvertices;j++)
9594                                 {
9595                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9596                                         numvertices++;
9597                                 }
9598                         }
9599                 }
9600         }
9601
9602         // if vertices are deformed (sprite flares and things in maps, possibly
9603         // water waves, bulges and other deformations), modify the copied vertices
9604         // in place
9605         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9606         {
9607                 float scale;
9608                 switch (deform->deform)
9609                 {
9610                 default:
9611                 case Q3DEFORM_PROJECTIONSHADOW:
9612                 case Q3DEFORM_TEXT0:
9613                 case Q3DEFORM_TEXT1:
9614                 case Q3DEFORM_TEXT2:
9615                 case Q3DEFORM_TEXT3:
9616                 case Q3DEFORM_TEXT4:
9617                 case Q3DEFORM_TEXT5:
9618                 case Q3DEFORM_TEXT6:
9619                 case Q3DEFORM_TEXT7:
9620                 case Q3DEFORM_NONE:
9621                         break;
9622                 case Q3DEFORM_AUTOSPRITE:
9623                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9624                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9625                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9626                         VectorNormalize(newforward);
9627                         VectorNormalize(newright);
9628                         VectorNormalize(newup);
9629 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9630 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9631 //                      rsurface.batchvertex3f_bufferoffset = 0;
9632 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9633 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9634 //                      rsurface.batchsvector3f_bufferoffset = 0;
9635 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9636 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9637 //                      rsurface.batchtvector3f_bufferoffset = 0;
9638 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9639 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9640 //                      rsurface.batchnormal3f_bufferoffset = 0;
9641                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9642                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9643                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9644                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9645                                 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);
9646                         // a single autosprite surface can contain multiple sprites...
9647                         for (j = 0;j < batchnumvertices - 3;j += 4)
9648                         {
9649                                 VectorClear(center);
9650                                 for (i = 0;i < 4;i++)
9651                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9652                                 VectorScale(center, 0.25f, center);
9653                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9654                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9655                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9656                                 for (i = 0;i < 4;i++)
9657                                 {
9658                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9659                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9660                                 }
9661                         }
9662                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9663                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9664                         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);
9665                         break;
9666                 case Q3DEFORM_AUTOSPRITE2:
9667                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9668                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9670                         VectorNormalize(newforward);
9671                         VectorNormalize(newright);
9672                         VectorNormalize(newup);
9673 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9674 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9675 //                      rsurface.batchvertex3f_bufferoffset = 0;
9676                         {
9677                                 const float *v1, *v2;
9678                                 vec3_t start, end;
9679                                 float f, l;
9680                                 struct
9681                                 {
9682                                         float length2;
9683                                         const float *v1;
9684                                         const float *v2;
9685                                 }
9686                                 shortest[2];
9687                                 memset(shortest, 0, sizeof(shortest));
9688                                 // a single autosprite surface can contain multiple sprites...
9689                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9690                                 {
9691                                         VectorClear(center);
9692                                         for (i = 0;i < 4;i++)
9693                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9694                                         VectorScale(center, 0.25f, center);
9695                                         // find the two shortest edges, then use them to define the
9696                                         // axis vectors for rotating around the central axis
9697                                         for (i = 0;i < 6;i++)
9698                                         {
9699                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9700                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9701                                                 l = VectorDistance2(v1, v2);
9702                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9703                                                 if (v1[2] != v2[2])
9704                                                         l += (1.0f / 1024.0f);
9705                                                 if (shortest[0].length2 > l || i == 0)
9706                                                 {
9707                                                         shortest[1] = shortest[0];
9708                                                         shortest[0].length2 = l;
9709                                                         shortest[0].v1 = v1;
9710                                                         shortest[0].v2 = v2;
9711                                                 }
9712                                                 else if (shortest[1].length2 > l || i == 1)
9713                                                 {
9714                                                         shortest[1].length2 = l;
9715                                                         shortest[1].v1 = v1;
9716                                                         shortest[1].v2 = v2;
9717                                                 }
9718                                         }
9719                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9720                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9721                                         // this calculates the right vector from the shortest edge
9722                                         // and the up vector from the edge midpoints
9723                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9724                                         VectorNormalize(right);
9725                                         VectorSubtract(end, start, up);
9726                                         VectorNormalize(up);
9727                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9728                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9729                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9730                                         VectorNegate(forward, forward);
9731                                         VectorReflect(forward, 0, up, forward);
9732                                         VectorNormalize(forward);
9733                                         CrossProduct(up, forward, newright);
9734                                         VectorNormalize(newright);
9735                                         // rotate the quad around the up axis vector, this is made
9736                                         // especially easy by the fact we know the quad is flat,
9737                                         // so we only have to subtract the center position and
9738                                         // measure distance along the right vector, and then
9739                                         // multiply that by the newright vector and add back the
9740                                         // center position
9741                                         // we also need to subtract the old position to undo the
9742                                         // displacement from the center, which we do with a
9743                                         // DotProduct, the subtraction/addition of center is also
9744                                         // optimized into DotProducts here
9745                                         l = DotProduct(right, center);
9746                                         for (i = 0;i < 4;i++)
9747                                         {
9748                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9749                                                 f = DotProduct(right, v1) - l;
9750                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9751                                         }
9752                                 }
9753                         }
9754                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9755                         {
9756 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9757 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9758 //                              rsurface.batchnormal3f_bufferoffset = 0;
9759                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9760                         }
9761                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9762                         {
9763 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9764 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9765 //                              rsurface.batchsvector3f_bufferoffset = 0;
9766 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9767 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9768 //                              rsurface.batchtvector3f_bufferoffset = 0;
9769                                 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);
9770                         }
9771                         break;
9772                 case Q3DEFORM_NORMAL:
9773                         // deform the normals to make reflections wavey
9774                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9775                         rsurface.batchnormal3f_vertexbuffer = NULL;
9776                         rsurface.batchnormal3f_bufferoffset = 0;
9777                         for (j = 0;j < batchnumvertices;j++)
9778                         {
9779                                 float vertex[3];
9780                                 float *normal = rsurface.batchnormal3f + 3*j;
9781                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9782                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9783                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9784                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9785                                 VectorNormalize(normal);
9786                         }
9787                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9788                         {
9789 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9790 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9791 //                              rsurface.batchsvector3f_bufferoffset = 0;
9792 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9793 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9794 //                              rsurface.batchtvector3f_bufferoffset = 0;
9795                                 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);
9796                         }
9797                         break;
9798                 case Q3DEFORM_WAVE:
9799                         // deform vertex array to make wavey water and flags and such
9800                         waveparms[0] = deform->waveparms[0];
9801                         waveparms[1] = deform->waveparms[1];
9802                         waveparms[2] = deform->waveparms[2];
9803                         waveparms[3] = deform->waveparms[3];
9804                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9805                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9806                         // this is how a divisor of vertex influence on deformation
9807                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9808                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9809 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9810 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9811 //                      rsurface.batchvertex3f_bufferoffset = 0;
9812 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9813 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9814 //                      rsurface.batchnormal3f_bufferoffset = 0;
9815                         for (j = 0;j < batchnumvertices;j++)
9816                         {
9817                                 // if the wavefunc depends on time, evaluate it per-vertex
9818                                 if (waveparms[3])
9819                                 {
9820                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9821                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9822                                 }
9823                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9824                         }
9825                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9826                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9827                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9828                         {
9829 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9830 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9831 //                              rsurface.batchsvector3f_bufferoffset = 0;
9832 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9833 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9834 //                              rsurface.batchtvector3f_bufferoffset = 0;
9835                                 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);
9836                         }
9837                         break;
9838                 case Q3DEFORM_BULGE:
9839                         // deform vertex array to make the surface have moving bulges
9840 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9841 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9842 //                      rsurface.batchvertex3f_bufferoffset = 0;
9843 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9844 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9845 //                      rsurface.batchnormal3f_bufferoffset = 0;
9846                         for (j = 0;j < batchnumvertices;j++)
9847                         {
9848                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9849                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9850                         }
9851                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9852                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9853                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9854                         {
9855 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9856 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9857 //                              rsurface.batchsvector3f_bufferoffset = 0;
9858 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9859 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9860 //                              rsurface.batchtvector3f_bufferoffset = 0;
9861                                 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);
9862                         }
9863                         break;
9864                 case Q3DEFORM_MOVE:
9865                         // deform vertex array
9866                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9867                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9868                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9869                         VectorScale(deform->parms, scale, waveparms);
9870 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9871 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9872 //                      rsurface.batchvertex3f_bufferoffset = 0;
9873                         for (j = 0;j < batchnumvertices;j++)
9874                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9875                         break;
9876                 }
9877         }
9878
9879         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9880         {
9881         // generate texcoords based on the chosen texcoord source
9882                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9883                 {
9884                 default:
9885                 case Q3TCGEN_TEXTURE:
9886                         break;
9887                 case Q3TCGEN_LIGHTMAP:
9888         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9889         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9890         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9891                         if (rsurface.batchtexcoordlightmap2f)
9892                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9893                         break;
9894                 case Q3TCGEN_VECTOR:
9895         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9896         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9897         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9898                         for (j = 0;j < batchnumvertices;j++)
9899                         {
9900                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9901                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9902                         }
9903                         break;
9904                 case Q3TCGEN_ENVIRONMENT:
9905                         // make environment reflections using a spheremap
9906                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9907                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9908                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9909                         for (j = 0;j < batchnumvertices;j++)
9910                         {
9911                                 // identical to Q3A's method, but executed in worldspace so
9912                                 // carried models can be shiny too
9913
9914                                 float viewer[3], d, reflected[3], worldreflected[3];
9915
9916                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9917                                 // VectorNormalize(viewer);
9918
9919                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9920
9921                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9922                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9923                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9924                                 // note: this is proportinal to viewer, so we can normalize later
9925
9926                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9927                                 VectorNormalize(worldreflected);
9928
9929                                 // note: this sphere map only uses world x and z!
9930                                 // so positive and negative y will LOOK THE SAME.
9931                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9932                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9933                         }
9934                         break;
9935                 }
9936                 // the only tcmod that needs software vertex processing is turbulent, so
9937                 // check for it here and apply the changes if needed
9938                 // and we only support that as the first one
9939                 // (handling a mixture of turbulent and other tcmods would be problematic
9940                 //  without punting it entirely to a software path)
9941                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9942                 {
9943                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9944                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9945         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9946         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9947         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9948                         for (j = 0;j < batchnumvertices;j++)
9949                         {
9950                                 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);
9951                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9952                         }
9953                 }
9954         }
9955
9956         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9957         {
9958                 // convert the modified arrays to vertex structs
9959 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9960 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
9961 //              rsurface.batchvertexmesh_bufferoffset = 0;
9962                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9963                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9964                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9965                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9966                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9967                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9968                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9969                 {
9970                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9971                         {
9972                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9973                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9974                         }
9975                 }
9976                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9977                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9978                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9979                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9980                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9981                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9982                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9983                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9984                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9985                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9986                 {
9987                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9988                         {
9989                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9990                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9991                         }
9992                 }
9993         }
9994
9995         // upload buffer data for the dynamic batch
9996         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9997         {
9998                 if (rsurface.batchvertexmesh)
9999                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10000                 else
10001                 {
10002                         if (rsurface.batchvertex3f)
10003                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10004                         if (rsurface.batchsvector3f)
10005                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10006                         if (rsurface.batchtvector3f)
10007                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10008                         if (rsurface.batchnormal3f)
10009                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10010                         if (rsurface.batchlightmapcolor4f)
10011                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10012                         if (rsurface.batchtexcoordtexture2f)
10013                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10014                         if (rsurface.batchtexcoordlightmap2f)
10015                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10016                         if (rsurface.batchskeletalindex4ub)
10017                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10018                         if (rsurface.batchskeletalweight4ub)
10019                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10020                 }
10021                 if (rsurface.batchelement3s)
10022                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10023                 else if (rsurface.batchelement3i)
10024                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10025         }
10026 }
10027
10028 void RSurf_DrawBatch(void)
10029 {
10030         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10031         // through the pipeline, killing it earlier in the pipeline would have
10032         // per-surface overhead rather than per-batch overhead, so it's best to
10033         // reject it here, before it hits glDraw.
10034         if (rsurface.batchnumtriangles == 0)
10035                 return;
10036 #if 0
10037         // batch debugging code
10038         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10039         {
10040                 int i;
10041                 int j;
10042                 int c;
10043                 const int *e;
10044                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10045                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10046                 {
10047                         c = e[i];
10048                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10049                         {
10050                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10051                                 {
10052                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10053                                                 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);
10054                                         break;
10055                                 }
10056                         }
10057                 }
10058         }
10059 #endif
10060         if (rsurface.batchmultidraw)
10061         {
10062                 // issue multiple draws rather than copying index data
10063                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10064                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10065                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10066                 for (i = 0;i < numsurfaces;)
10067                 {
10068                         // combine consecutive surfaces as one draw
10069                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10070                                 if (surfacelist[j] != surfacelist[k] + 1)
10071                                         break;
10072                         firstvertex = surfacelist[i]->num_firstvertex;
10073                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10074                         firsttriangle = surfacelist[i]->num_firsttriangle;
10075                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10076                         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);
10077                         i = j;
10078                 }
10079         }
10080         else
10081         {
10082                 // there is only one consecutive run of index data (may have been combined)
10083                 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);
10084         }
10085 }
10086
10087 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10088 {
10089         // pick the closest matching water plane
10090         int planeindex, vertexindex, bestplaneindex = -1;
10091         float d, bestd;
10092         vec3_t vert;
10093         const float *v;
10094         r_waterstate_waterplane_t *p;
10095         qboolean prepared = false;
10096         bestd = 0;
10097         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10098         {
10099                 if(p->camera_entity != rsurface.texture->camera_entity)
10100                         continue;
10101                 d = 0;
10102                 if(!prepared)
10103                 {
10104                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10105                         prepared = true;
10106                         if(rsurface.batchnumvertices == 0)
10107                                 break;
10108                 }
10109                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10110                 {
10111                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10112                         d += fabs(PlaneDiff(vert, &p->plane));
10113                 }
10114                 if (bestd > d || bestplaneindex < 0)
10115                 {
10116                         bestd = d;
10117                         bestplaneindex = planeindex;
10118                 }
10119         }
10120         return bestplaneindex;
10121         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10122         // this situation though, as it might be better to render single larger
10123         // batches with useless stuff (backface culled for example) than to
10124         // render multiple smaller batches
10125 }
10126
10127 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10128 {
10129         int i;
10130         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10131         rsurface.passcolor4f_vertexbuffer = 0;
10132         rsurface.passcolor4f_bufferoffset = 0;
10133         for (i = 0;i < rsurface.batchnumvertices;i++)
10134                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10135 }
10136
10137 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10138 {
10139         int i;
10140         float f;
10141         const float *v;
10142         const float *c;
10143         float *c2;
10144         if (rsurface.passcolor4f)
10145         {
10146                 // generate color arrays
10147                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10148                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10149                 rsurface.passcolor4f_vertexbuffer = 0;
10150                 rsurface.passcolor4f_bufferoffset = 0;
10151                 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)
10152                 {
10153                         f = RSurf_FogVertex(v);
10154                         c2[0] = c[0] * f;
10155                         c2[1] = c[1] * f;
10156                         c2[2] = c[2] * f;
10157                         c2[3] = c[3];
10158                 }
10159         }
10160         else
10161         {
10162                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10163                 rsurface.passcolor4f_vertexbuffer = 0;
10164                 rsurface.passcolor4f_bufferoffset = 0;
10165                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10166                 {
10167                         f = RSurf_FogVertex(v);
10168                         c2[0] = f;
10169                         c2[1] = f;
10170                         c2[2] = f;
10171                         c2[3] = 1;
10172                 }
10173         }
10174 }
10175
10176 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10177 {
10178         int i;
10179         float f;
10180         const float *v;
10181         const float *c;
10182         float *c2;
10183         if (!rsurface.passcolor4f)
10184                 return;
10185         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10186         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10187         rsurface.passcolor4f_vertexbuffer = 0;
10188         rsurface.passcolor4f_bufferoffset = 0;
10189         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)
10190         {
10191                 f = RSurf_FogVertex(v);
10192                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10193                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10194                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10195                 c2[3] = c[3];
10196         }
10197 }
10198
10199 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10200 {
10201         int i;
10202         const float *c;
10203         float *c2;
10204         if (!rsurface.passcolor4f)
10205                 return;
10206         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10207         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10208         rsurface.passcolor4f_vertexbuffer = 0;
10209         rsurface.passcolor4f_bufferoffset = 0;
10210         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10211         {
10212                 c2[0] = c[0] * r;
10213                 c2[1] = c[1] * g;
10214                 c2[2] = c[2] * b;
10215                 c2[3] = c[3] * a;
10216         }
10217 }
10218
10219 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10220 {
10221         int i;
10222         const float *c;
10223         float *c2;
10224         if (!rsurface.passcolor4f)
10225                 return;
10226         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10227         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10228         rsurface.passcolor4f_vertexbuffer = 0;
10229         rsurface.passcolor4f_bufferoffset = 0;
10230         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10231         {
10232                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10233                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10234                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10235                 c2[3] = c[3];
10236         }
10237 }
10238
10239 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10240 {
10241         // TODO: optimize
10242         rsurface.passcolor4f = NULL;
10243         rsurface.passcolor4f_vertexbuffer = 0;
10244         rsurface.passcolor4f_bufferoffset = 0;
10245         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10246         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10247         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10248         GL_Color(r, g, b, a);
10249         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10250         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10251         R_Mesh_TexMatrix(0, NULL);
10252         RSurf_DrawBatch();
10253 }
10254
10255 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10256 {
10257         // TODO: optimize applyfog && applycolor case
10258         // just apply fog if necessary, and tint the fog color array if necessary
10259         rsurface.passcolor4f = NULL;
10260         rsurface.passcolor4f_vertexbuffer = 0;
10261         rsurface.passcolor4f_bufferoffset = 0;
10262         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10263         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10264         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10265         GL_Color(r, g, b, a);
10266         RSurf_DrawBatch();
10267 }
10268
10269 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10270 {
10271         // TODO: optimize
10272         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10273         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10274         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10275         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10276         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10277         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10278         GL_Color(r, g, b, a);
10279         RSurf_DrawBatch();
10280 }
10281
10282 static void RSurf_DrawBatch_GL11_ClampColor(void)
10283 {
10284         int i;
10285         const float *c1;
10286         float *c2;
10287         if (!rsurface.passcolor4f)
10288                 return;
10289         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10290         {
10291                 c2[0] = bound(0.0f, c1[0], 1.0f);
10292                 c2[1] = bound(0.0f, c1[1], 1.0f);
10293                 c2[2] = bound(0.0f, c1[2], 1.0f);
10294                 c2[3] = bound(0.0f, c1[3], 1.0f);
10295         }
10296 }
10297
10298 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10299 {
10300         int i;
10301         float f;
10302         const float *v;
10303         const float *n;
10304         float *c;
10305         //vec3_t eyedir;
10306
10307         // fake shading
10308         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10309         rsurface.passcolor4f_vertexbuffer = 0;
10310         rsurface.passcolor4f_bufferoffset = 0;
10311         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)
10312         {
10313                 f = -DotProduct(r_refdef.view.forward, n);
10314                 f = max(0, f);
10315                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10316                 f *= fakelightintensity;
10317                 Vector4Set(c, f, f, f, 1);
10318         }
10319 }
10320
10321 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10322 {
10323         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10324         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10325         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10326         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10327         GL_Color(r, g, b, a);
10328         RSurf_DrawBatch();
10329 }
10330
10331 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10332 {
10333         int i;
10334         float f;
10335         float alpha;
10336         const float *v;
10337         const float *n;
10338         float *c;
10339         vec3_t ambientcolor;
10340         vec3_t diffusecolor;
10341         vec3_t lightdir;
10342         // TODO: optimize
10343         // model lighting
10344         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10345         f = 0.5f * lightmapintensity;
10346         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10347         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10348         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10349         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10350         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10351         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10352         alpha = *a;
10353         if (VectorLength2(diffusecolor) > 0)
10354         {
10355                 // q3-style directional shading
10356                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10357                 rsurface.passcolor4f_vertexbuffer = 0;
10358                 rsurface.passcolor4f_bufferoffset = 0;
10359                 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)
10360                 {
10361                         if ((f = DotProduct(n, lightdir)) > 0)
10362                                 VectorMA(ambientcolor, f, diffusecolor, c);
10363                         else
10364                                 VectorCopy(ambientcolor, c);
10365                         c[3] = alpha;
10366                 }
10367                 *r = 1;
10368                 *g = 1;
10369                 *b = 1;
10370                 *a = 1;
10371                 *applycolor = false;
10372         }
10373         else
10374         {
10375                 *r = ambientcolor[0];
10376                 *g = ambientcolor[1];
10377                 *b = ambientcolor[2];
10378                 rsurface.passcolor4f = NULL;
10379                 rsurface.passcolor4f_vertexbuffer = 0;
10380                 rsurface.passcolor4f_bufferoffset = 0;
10381         }
10382 }
10383
10384 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10385 {
10386         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10387         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10388         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10389         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10390         GL_Color(r, g, b, a);
10391         RSurf_DrawBatch();
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10395 {
10396         int i;
10397         float f;
10398         const float *v;
10399         float *c;
10400
10401         // fake shading
10402         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10403         rsurface.passcolor4f_vertexbuffer = 0;
10404         rsurface.passcolor4f_bufferoffset = 0;
10405
10406         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10407         {
10408                 f = 1 - RSurf_FogVertex(v);
10409                 c[0] = r;
10410                 c[1] = g;
10411                 c[2] = b;
10412                 c[3] = f * a;
10413         }
10414 }
10415
10416 void RSurf_SetupDepthAndCulling(void)
10417 {
10418         // submodels are biased to avoid z-fighting with world surfaces that they
10419         // may be exactly overlapping (avoids z-fighting artifacts on certain
10420         // doors and things in Quake maps)
10421         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10422         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10423         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10424         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10425 }
10426
10427 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10428 {
10429         int i, j;
10430         // transparent sky would be ridiculous
10431         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10432                 return;
10433         R_SetupShader_Generic_NoTexture(false, false);
10434         skyrenderlater = true;
10435         RSurf_SetupDepthAndCulling();
10436         GL_DepthMask(true);
10437
10438         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10439         if (r_sky_scissor.integer)
10440         {
10441                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10442                 for (i = 0; i < texturenumsurfaces; i++)
10443                 {
10444                         const msurface_t *surf = texturesurfacelist[i];
10445                         const float *v;
10446                         float p[3];
10447                         float mins[3], maxs[3];
10448                         int scissor[4];
10449                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10450                         {
10451                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10452                                 if (j > 0)
10453                                 {
10454                                         if (mins[0] > p[0]) mins[0] = p[0];
10455                                         if (mins[1] > p[1]) mins[1] = p[1];
10456                                         if (mins[2] > p[2]) mins[2] = p[2];
10457                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10458                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10459                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10460                                 }
10461                                 else
10462                                 {
10463                                         VectorCopy(p, mins);
10464                                         VectorCopy(p, maxs);
10465                                 }
10466                         }
10467                         if (!R_ScissorForBBox(mins, maxs, scissor))
10468                         {
10469                                 if (skyscissor[2])
10470                                 {
10471                                         if (skyscissor[0] > scissor[0])
10472                                         {
10473                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10474                                                 skyscissor[0] = scissor[0];
10475                                         }
10476                                         if (skyscissor[1] > scissor[1])
10477                                         {
10478                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10479                                                 skyscissor[1] = scissor[1];
10480                                         }
10481                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10482                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10483                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10484                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10485                                 }
10486                                 else
10487                                         Vector4Copy(scissor, skyscissor);
10488                         }
10489                 }
10490         }
10491
10492         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10493         // skymasking on them, and Quake3 never did sky masking (unlike
10494         // software Quake and software Quake2), so disable the sky masking
10495         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10496         // and skymasking also looks very bad when noclipping outside the
10497         // level, so don't use it then either.
10498         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10499         {
10500                 R_Mesh_ResetTextureState();
10501                 if (skyrendermasked)
10502                 {
10503                         R_SetupShader_DepthOrShadow(false, false, false);
10504                         // depth-only (masking)
10505                         GL_ColorMask(0, 0, 0, 0);
10506                         // just to make sure that braindead drivers don't draw
10507                         // anything despite that colormask...
10508                         GL_BlendFunc(GL_ZERO, GL_ONE);
10509                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10510                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10511                 }
10512                 else
10513                 {
10514                         R_SetupShader_Generic_NoTexture(false, false);
10515                         // fog sky
10516                         GL_BlendFunc(GL_ONE, GL_ZERO);
10517                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10518                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10519                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10520                 }
10521                 RSurf_DrawBatch();
10522                 if (skyrendermasked)
10523                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10524         }
10525         R_Mesh_ResetTextureState();
10526         GL_Color(1, 1, 1, 1);
10527 }
10528
10529 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10530 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10531 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10532 {
10533         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10534                 return;
10535         if (prepass)
10536         {
10537                 // render screenspace normalmap to texture
10538                 GL_DepthMask(true);
10539                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10540                 RSurf_DrawBatch();
10541                 return;
10542         }
10543
10544         // bind lightmap texture
10545
10546         // water/refraction/reflection/camera surfaces have to be handled specially
10547         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10548         {
10549                 int start, end, startplaneindex;
10550                 for (start = 0;start < texturenumsurfaces;start = end)
10551                 {
10552                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10553                         if(startplaneindex < 0)
10554                         {
10555                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10556                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10557                                 end = start + 1;
10558                                 continue;
10559                         }
10560                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10561                                 ;
10562                         // now that we have a batch using the same planeindex, render it
10563                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10564                         {
10565                                 // render water or distortion background
10566                                 GL_DepthMask(true);
10567                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10568                                 RSurf_DrawBatch();
10569                                 // blend surface on top
10570                                 GL_DepthMask(false);
10571                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10572                                 RSurf_DrawBatch();
10573                         }
10574                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10575                         {
10576                                 // render surface with reflection texture as input
10577                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10578                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10579                                 RSurf_DrawBatch();
10580                         }
10581                 }
10582                 return;
10583         }
10584
10585         // render surface batch normally
10586         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10587         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10588         RSurf_DrawBatch();
10589 }
10590
10591 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10592 {
10593         // OpenGL 1.3 path - anything not completely ancient
10594         qboolean applycolor;
10595         qboolean applyfog;
10596         int layerindex;
10597         const texturelayer_t *layer;
10598         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10599         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10600
10601         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10602         {
10603                 vec4_t layercolor;
10604                 int layertexrgbscale;
10605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10606                 {
10607                         if (layerindex == 0)
10608                                 GL_AlphaTest(true);
10609                         else
10610                         {
10611                                 GL_AlphaTest(false);
10612                                 GL_DepthFunc(GL_EQUAL);
10613                         }
10614                 }
10615                 GL_DepthMask(layer->depthmask && writedepth);
10616                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10617                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10618                 {
10619                         layertexrgbscale = 4;
10620                         VectorScale(layer->color, 0.25f, layercolor);
10621                 }
10622                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10623                 {
10624                         layertexrgbscale = 2;
10625                         VectorScale(layer->color, 0.5f, layercolor);
10626                 }
10627                 else
10628                 {
10629                         layertexrgbscale = 1;
10630                         VectorScale(layer->color, 1.0f, layercolor);
10631                 }
10632                 layercolor[3] = layer->color[3];
10633                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10634                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10635                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10636                 switch (layer->type)
10637                 {
10638                 case TEXTURELAYERTYPE_LITTEXTURE:
10639                         // single-pass lightmapped texture with 2x rgbscale
10640                         R_Mesh_TexBind(0, r_texture_white);
10641                         R_Mesh_TexMatrix(0, NULL);
10642                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10643                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10644                         R_Mesh_TexBind(1, layer->texture);
10645                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10646                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10647                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10648                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10649                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10650                         else if (FAKELIGHT_ENABLED)
10651                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10652                         else if (rsurface.uselightmaptexture)
10653                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10654                         else
10655                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10656                         break;
10657                 case TEXTURELAYERTYPE_TEXTURE:
10658                         // singletexture unlit texture with transparency support
10659                         R_Mesh_TexBind(0, layer->texture);
10660                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10661                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10662                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10663                         R_Mesh_TexBind(1, 0);
10664                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10665                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10666                         break;
10667                 case TEXTURELAYERTYPE_FOG:
10668                         // singletexture fogging
10669                         if (layer->texture)
10670                         {
10671                                 R_Mesh_TexBind(0, layer->texture);
10672                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10673                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10674                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10675                         }
10676                         else
10677                         {
10678                                 R_Mesh_TexBind(0, 0);
10679                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10680                         }
10681                         R_Mesh_TexBind(1, 0);
10682                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10683                         // generate a color array for the fog pass
10684                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10685                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10686                         RSurf_DrawBatch();
10687                         break;
10688                 default:
10689                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10690                 }
10691         }
10692         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10693         {
10694                 GL_DepthFunc(GL_LEQUAL);
10695                 GL_AlphaTest(false);
10696         }
10697 }
10698
10699 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10700 {
10701         // OpenGL 1.1 - crusty old voodoo path
10702         qboolean applyfog;
10703         int layerindex;
10704         const texturelayer_t *layer;
10705         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10706         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10707
10708         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10709         {
10710                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10711                 {
10712                         if (layerindex == 0)
10713                                 GL_AlphaTest(true);
10714                         else
10715                         {
10716                                 GL_AlphaTest(false);
10717                                 GL_DepthFunc(GL_EQUAL);
10718                         }
10719                 }
10720                 GL_DepthMask(layer->depthmask && writedepth);
10721                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10722                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10723                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10724                 switch (layer->type)
10725                 {
10726                 case TEXTURELAYERTYPE_LITTEXTURE:
10727                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10728                         {
10729                                 // two-pass lit texture with 2x rgbscale
10730                                 // first the lightmap pass
10731                                 R_Mesh_TexBind(0, r_texture_white);
10732                                 R_Mesh_TexMatrix(0, NULL);
10733                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10734                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10735                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10736                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10737                                 else if (FAKELIGHT_ENABLED)
10738                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10739                                 else if (rsurface.uselightmaptexture)
10740                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10741                                 else
10742                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10743                                 // then apply the texture to it
10744                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10745                                 R_Mesh_TexBind(0, layer->texture);
10746                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10747                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10748                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10749                                 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);
10750                         }
10751                         else
10752                         {
10753                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10754                                 R_Mesh_TexBind(0, layer->texture);
10755                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10756                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10757                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10758                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10759                                         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);
10760                                 else if (FAKELIGHT_ENABLED)
10761                                         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);
10762                                 else
10763                                         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);
10764                         }
10765                         break;
10766                 case TEXTURELAYERTYPE_TEXTURE:
10767                         // singletexture unlit texture with transparency support
10768                         R_Mesh_TexBind(0, layer->texture);
10769                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10770                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10771                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10772                         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);
10773                         break;
10774                 case TEXTURELAYERTYPE_FOG:
10775                         // singletexture fogging
10776                         if (layer->texture)
10777                         {
10778                                 R_Mesh_TexBind(0, layer->texture);
10779                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10780                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10781                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10782                         }
10783                         else
10784                         {
10785                                 R_Mesh_TexBind(0, 0);
10786                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10787                         }
10788                         // generate a color array for the fog pass
10789                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10790                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10791                         RSurf_DrawBatch();
10792                         break;
10793                 default:
10794                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10795                 }
10796         }
10797         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10798         {
10799                 GL_DepthFunc(GL_LEQUAL);
10800                 GL_AlphaTest(false);
10801         }
10802 }
10803
10804 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10805 {
10806         int vi;
10807         int j;
10808         r_vertexgeneric_t *batchvertex;
10809         float c[4];
10810         texture_t *t = rsurface.texture;
10811
10812 //      R_Mesh_ResetTextureState();
10813         R_SetupShader_Generic_NoTexture(false, false);
10814
10815         if(t && t->currentskinframe)
10816         {
10817                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10818                 c[3] *= t->currentalpha;
10819         }
10820         else
10821         {
10822                 c[0] = 1;
10823                 c[1] = 0;
10824                 c[2] = 1;
10825                 c[3] = 1;
10826         }
10827
10828         if (t->pantstexture || t->shirttexture)
10829         {
10830                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10831                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10832                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10833         }
10834
10835         // brighten it up (as texture value 127 means "unlit")
10836         c[0] *= 2 * r_refdef.view.colorscale;
10837         c[1] *= 2 * r_refdef.view.colorscale;
10838         c[2] *= 2 * r_refdef.view.colorscale;
10839
10840         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10841                 c[3] *= r_wateralpha.value;
10842
10843         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10844         {
10845                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10846                 GL_DepthMask(false);
10847         }
10848         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10849         {
10850                 GL_BlendFunc(GL_ONE, GL_ONE);
10851                 GL_DepthMask(false);
10852         }
10853         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10854         {
10855                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10856                 GL_DepthMask(false);
10857         }
10858         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10859         {
10860                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10861                 GL_DepthMask(false);
10862         }
10863         else
10864         {
10865                 GL_BlendFunc(GL_ONE, GL_ZERO);
10866                 GL_DepthMask(writedepth);
10867         }
10868
10869         if (r_showsurfaces.integer == 3)
10870         {
10871                 rsurface.passcolor4f = NULL;
10872
10873                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10874                 {
10875                         qboolean applycolor = true;
10876                         float one = 1.0;
10877
10878                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10879
10880                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10881                 }
10882                 else if (FAKELIGHT_ENABLED)
10883                 {
10884                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10885
10886                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10887                 }
10888                 else
10889                 {
10890                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10891
10892                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10893                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10894                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10895                         RSurf_DrawBatch_GL11_ApplyAmbient();
10896                 }
10897
10898                 if(!rsurface.passcolor4f)
10899                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10900
10901                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10902                 if(r_refdef.fogenabled)
10903                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10904                 RSurf_DrawBatch_GL11_ClampColor();
10905
10906                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10907                 R_SetupShader_Generic_NoTexture(false, false);
10908                 RSurf_DrawBatch();
10909         }
10910         else if (!r_refdef.view.showdebug)
10911         {
10912                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10913                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10914                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10915                 {
10916                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10917                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10918                 }
10919                 R_Mesh_PrepareVertices_Generic_Unlock();
10920                 RSurf_DrawBatch();
10921         }
10922         else if (r_showsurfaces.integer == 4)
10923         {
10924                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10925                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10926                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10927                 {
10928                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
10929                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10930                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10931                 }
10932                 R_Mesh_PrepareVertices_Generic_Unlock();
10933                 RSurf_DrawBatch();
10934         }
10935         else if (r_showsurfaces.integer == 2)
10936         {
10937                 const int *e;
10938                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10939                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10940                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10941                 {
10942                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10943                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10944                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10945                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10946                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10947                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10948                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10949                 }
10950                 R_Mesh_PrepareVertices_Generic_Unlock();
10951                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10952         }
10953         else
10954         {
10955                 int texturesurfaceindex;
10956                 int k;
10957                 const msurface_t *surface;
10958                 float surfacecolor4f[4];
10959                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10961                 vi = 0;
10962                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10963                 {
10964                         surface = texturesurfacelist[texturesurfaceindex];
10965                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10966                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10967                         for (j = 0;j < surface->num_vertices;j++)
10968                         {
10969                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10970                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10971                                 vi++;
10972                         }
10973                 }
10974                 R_Mesh_PrepareVertices_Generic_Unlock();
10975                 RSurf_DrawBatch();
10976         }
10977 }
10978
10979 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10980 {
10981         CHECKGLERROR
10982         RSurf_SetupDepthAndCulling();
10983         if (r_showsurfaces.integer)
10984         {
10985                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10986                 return;
10987         }
10988         switch (vid.renderpath)
10989         {
10990         case RENDERPATH_GL20:
10991         case RENDERPATH_D3D9:
10992         case RENDERPATH_D3D10:
10993         case RENDERPATH_D3D11:
10994         case RENDERPATH_SOFT:
10995         case RENDERPATH_GLES2:
10996                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10997                 break;
10998         case RENDERPATH_GL13:
10999         case RENDERPATH_GLES1:
11000                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11001                 break;
11002         case RENDERPATH_GL11:
11003                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11004                 break;
11005         }
11006         CHECKGLERROR
11007 }
11008
11009 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11010 {
11011         int i, j;
11012         int texturenumsurfaces, endsurface;
11013         texture_t *texture;
11014         const msurface_t *surface;
11015         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11016
11017         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11018                 RSurf_ActiveModelEntity(ent, false, false, false);
11019         else
11020         {
11021                 switch (vid.renderpath)
11022                 {
11023                 case RENDERPATH_GL20:
11024                 case RENDERPATH_D3D9:
11025                 case RENDERPATH_D3D10:
11026                 case RENDERPATH_D3D11:
11027                 case RENDERPATH_SOFT:
11028                 case RENDERPATH_GLES2:
11029                         RSurf_ActiveModelEntity(ent, true, true, false);
11030                         break;
11031                 case RENDERPATH_GL11:
11032                 case RENDERPATH_GL13:
11033                 case RENDERPATH_GLES1:
11034                         RSurf_ActiveModelEntity(ent, true, false, false);
11035                         break;
11036                 }
11037         }
11038
11039         if (r_transparentdepthmasking.integer)
11040         {
11041                 qboolean setup = false;
11042                 for (i = 0;i < numsurfaces;i = j)
11043                 {
11044                         j = i + 1;
11045                         surface = rsurface.modelsurfaces + surfacelist[i];
11046                         texture = surface->texture;
11047                         rsurface.texture = R_GetCurrentTexture(texture);
11048                         rsurface.lightmaptexture = NULL;
11049                         rsurface.deluxemaptexture = NULL;
11050                         rsurface.uselightmaptexture = false;
11051                         // scan ahead until we find a different texture
11052                         endsurface = min(i + 1024, numsurfaces);
11053                         texturenumsurfaces = 0;
11054                         texturesurfacelist[texturenumsurfaces++] = surface;
11055                         for (;j < endsurface;j++)
11056                         {
11057                                 surface = rsurface.modelsurfaces + surfacelist[j];
11058                                 if (texture != surface->texture)
11059                                         break;
11060                                 texturesurfacelist[texturenumsurfaces++] = surface;
11061                         }
11062                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11063                                 continue;
11064                         // render the range of surfaces as depth
11065                         if (!setup)
11066                         {
11067                                 setup = true;
11068                                 GL_ColorMask(0,0,0,0);
11069                                 GL_Color(1,1,1,1);
11070                                 GL_DepthTest(true);
11071                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11072                                 GL_DepthMask(true);
11073 //                              R_Mesh_ResetTextureState();
11074                         }
11075                         RSurf_SetupDepthAndCulling();
11076                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11077                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11078                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11079                         RSurf_DrawBatch();
11080                 }
11081                 if (setup)
11082                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11083         }
11084
11085         for (i = 0;i < numsurfaces;i = j)
11086         {
11087                 j = i + 1;
11088                 surface = rsurface.modelsurfaces + surfacelist[i];
11089                 texture = surface->texture;
11090                 rsurface.texture = R_GetCurrentTexture(texture);
11091                 // scan ahead until we find a different texture
11092                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11093                 texturenumsurfaces = 0;
11094                 texturesurfacelist[texturenumsurfaces++] = surface;
11095                 if(FAKELIGHT_ENABLED)
11096                 {
11097                         rsurface.lightmaptexture = NULL;
11098                         rsurface.deluxemaptexture = NULL;
11099                         rsurface.uselightmaptexture = false;
11100                         for (;j < endsurface;j++)
11101                         {
11102                                 surface = rsurface.modelsurfaces + surfacelist[j];
11103                                 if (texture != surface->texture)
11104                                         break;
11105                                 texturesurfacelist[texturenumsurfaces++] = surface;
11106                         }
11107                 }
11108                 else
11109                 {
11110                         rsurface.lightmaptexture = surface->lightmaptexture;
11111                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11112                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11113                         for (;j < endsurface;j++)
11114                         {
11115                                 surface = rsurface.modelsurfaces + surfacelist[j];
11116                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11117                                         break;
11118                                 texturesurfacelist[texturenumsurfaces++] = surface;
11119                         }
11120                 }
11121                 // render the range of surfaces
11122                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11123         }
11124         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11125 }
11126
11127 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11128 {
11129         // transparent surfaces get pushed off into the transparent queue
11130         int surfacelistindex;
11131         const msurface_t *surface;
11132         vec3_t tempcenter, center;
11133         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11134         {
11135                 surface = texturesurfacelist[surfacelistindex];
11136                 if (r_transparent_sortsurfacesbynearest.integer)
11137                 {
11138                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11139                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11140                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11141                 }
11142                 else
11143                 {
11144                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11145                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11146                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11147                 }
11148                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11149                 if (rsurface.entity->transparent_offset) // transparent offset
11150                 {
11151                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11152                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11153                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11154                 }
11155                 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);
11156         }
11157 }
11158
11159 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11160 {
11161         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11162                 return;
11163         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11164                 return;
11165         RSurf_SetupDepthAndCulling();
11166         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11167         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11168         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11169         RSurf_DrawBatch();
11170 }
11171
11172 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11173 {
11174         CHECKGLERROR
11175         if (depthonly)
11176                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11177         else if (prepass)
11178         {
11179                 if (!rsurface.texture->currentnumlayers)
11180                         return;
11181                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11182                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11183                 else
11184                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11185         }
11186         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11187                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11188         else if (!rsurface.texture->currentnumlayers)
11189                 return;
11190         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11191         {
11192                 // in the deferred case, transparent surfaces were queued during prepass
11193                 if (!r_shadow_usingdeferredprepass)
11194                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11195         }
11196         else
11197         {
11198                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11199                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11200         }
11201         CHECKGLERROR
11202 }
11203
11204 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11205 {
11206         int i, j;
11207         texture_t *texture;
11208         R_FrameData_SetMark();
11209         // break the surface list down into batches by texture and use of lightmapping
11210         for (i = 0;i < numsurfaces;i = j)
11211         {
11212                 j = i + 1;
11213                 // texture is the base texture pointer, rsurface.texture is the
11214                 // current frame/skin the texture is directing us to use (for example
11215                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11216                 // use skin 1 instead)
11217                 texture = surfacelist[i]->texture;
11218                 rsurface.texture = R_GetCurrentTexture(texture);
11219                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11220                 {
11221                         // if this texture is not the kind we want, skip ahead to the next one
11222                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11223                                 ;
11224                         continue;
11225                 }
11226                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11227                 {
11228                         rsurface.lightmaptexture = NULL;
11229                         rsurface.deluxemaptexture = NULL;
11230                         rsurface.uselightmaptexture = false;
11231                         // simply scan ahead until we find a different texture or lightmap state
11232                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11233                                 ;
11234                 }
11235                 else
11236                 {
11237                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11238                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11239                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11240                         // simply scan ahead until we find a different texture or lightmap state
11241                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11242                                 ;
11243                 }
11244                 // render the range of surfaces
11245                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11246         }
11247         R_FrameData_ReturnToMark();
11248 }
11249
11250 float locboxvertex3f[6*4*3] =
11251 {
11252         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11253         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11254         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11255         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11256         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11257         1,0,0, 0,0,0, 0,1,0, 1,1,0
11258 };
11259
11260 unsigned short locboxelements[6*2*3] =
11261 {
11262          0, 1, 2, 0, 2, 3,
11263          4, 5, 6, 4, 6, 7,
11264          8, 9,10, 8,10,11,
11265         12,13,14, 12,14,15,
11266         16,17,18, 16,18,19,
11267         20,21,22, 20,22,23
11268 };
11269
11270 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11271 {
11272         int i, j;
11273         cl_locnode_t *loc = (cl_locnode_t *)ent;
11274         vec3_t mins, size;
11275         float vertex3f[6*4*3];
11276         CHECKGLERROR
11277         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11278         GL_DepthMask(false);
11279         GL_DepthRange(0, 1);
11280         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11281         GL_DepthTest(true);
11282         GL_CullFace(GL_NONE);
11283         R_EntityMatrix(&identitymatrix);
11284
11285 //      R_Mesh_ResetTextureState();
11286
11287         i = surfacelist[0];
11288         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11289                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11290                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11291                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11292
11293         if (VectorCompare(loc->mins, loc->maxs))
11294         {
11295                 VectorSet(size, 2, 2, 2);
11296                 VectorMA(loc->mins, -0.5f, size, mins);
11297         }
11298         else
11299         {
11300                 VectorCopy(loc->mins, mins);
11301                 VectorSubtract(loc->maxs, loc->mins, size);
11302         }
11303
11304         for (i = 0;i < 6*4*3;)
11305                 for (j = 0;j < 3;j++, i++)
11306                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11307
11308         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11309         R_SetupShader_Generic_NoTexture(false, false);
11310         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11311 }
11312
11313 void R_DrawLocs(void)
11314 {
11315         int index;
11316         cl_locnode_t *loc, *nearestloc;
11317         vec3_t center;
11318         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11319         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11320         {
11321                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11322                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11323         }
11324 }
11325
11326 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11327 {
11328         if (decalsystem->decals)
11329                 Mem_Free(decalsystem->decals);
11330         memset(decalsystem, 0, sizeof(*decalsystem));
11331 }
11332
11333 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, unsigned int decalsequence)
11334 {
11335         tridecal_t *decal;
11336         tridecal_t *decals;
11337         int i;
11338
11339         // expand or initialize the system
11340         if (decalsystem->maxdecals <= decalsystem->numdecals)
11341         {
11342                 decalsystem_t old = *decalsystem;
11343                 qboolean useshortelements;
11344                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11345                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11346                 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)));
11347                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11348                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11349                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11350                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11351                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11352                 if (decalsystem->numdecals)
11353                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11354                 if (old.decals)
11355                         Mem_Free(old.decals);
11356                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11357                         decalsystem->element3i[i] = i;
11358                 if (useshortelements)
11359                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11360                                 decalsystem->element3s[i] = i;
11361         }
11362
11363         // grab a decal and search for another free slot for the next one
11364         decals = decalsystem->decals;
11365         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11366         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11367                 ;
11368         decalsystem->freedecal = i;
11369         if (decalsystem->numdecals <= i)
11370                 decalsystem->numdecals = i + 1;
11371
11372         // initialize the decal
11373         decal->lived = 0;
11374         decal->triangleindex = triangleindex;
11375         decal->surfaceindex = surfaceindex;
11376         decal->decalsequence = decalsequence;
11377         decal->color4f[0][0] = c0[0];
11378         decal->color4f[0][1] = c0[1];
11379         decal->color4f[0][2] = c0[2];
11380         decal->color4f[0][3] = 1;
11381         decal->color4f[1][0] = c1[0];
11382         decal->color4f[1][1] = c1[1];
11383         decal->color4f[1][2] = c1[2];
11384         decal->color4f[1][3] = 1;
11385         decal->color4f[2][0] = c2[0];
11386         decal->color4f[2][1] = c2[1];
11387         decal->color4f[2][2] = c2[2];
11388         decal->color4f[2][3] = 1;
11389         decal->vertex3f[0][0] = v0[0];
11390         decal->vertex3f[0][1] = v0[1];
11391         decal->vertex3f[0][2] = v0[2];
11392         decal->vertex3f[1][0] = v1[0];
11393         decal->vertex3f[1][1] = v1[1];
11394         decal->vertex3f[1][2] = v1[2];
11395         decal->vertex3f[2][0] = v2[0];
11396         decal->vertex3f[2][1] = v2[1];
11397         decal->vertex3f[2][2] = v2[2];
11398         decal->texcoord2f[0][0] = t0[0];
11399         decal->texcoord2f[0][1] = t0[1];
11400         decal->texcoord2f[1][0] = t1[0];
11401         decal->texcoord2f[1][1] = t1[1];
11402         decal->texcoord2f[2][0] = t2[0];
11403         decal->texcoord2f[2][1] = t2[1];
11404         TriangleNormal(v0, v1, v2, decal->plane);
11405         VectorNormalize(decal->plane);
11406         decal->plane[3] = DotProduct(v0, decal->plane);
11407 }
11408
11409 extern cvar_t cl_decals_bias;
11410 extern cvar_t cl_decals_models;
11411 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11412 // baseparms, parms, temps
11413 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11414 {
11415         int cornerindex;
11416         int index;
11417         float v[9][3];
11418         const float *vertex3f;
11419         const float *normal3f;
11420         int numpoints;
11421         float points[2][9][3];
11422         float temp[3];
11423         float tc[9][2];
11424         float f;
11425         float c[9][4];
11426         const int *e;
11427
11428         e = rsurface.modelelement3i + 3*triangleindex;
11429
11430         vertex3f = rsurface.modelvertex3f;
11431         normal3f = rsurface.modelnormal3f;
11432
11433         if (normal3f)
11434         {
11435                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11436                 {
11437                         index = 3*e[cornerindex];
11438                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11439                 }
11440         }
11441         else
11442         {
11443                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11444                 {
11445                         index = 3*e[cornerindex];
11446                         VectorCopy(vertex3f + index, v[cornerindex]);
11447                 }
11448         }
11449
11450         // cull backfaces
11451         //TriangleNormal(v[0], v[1], v[2], normal);
11452         //if (DotProduct(normal, localnormal) < 0.0f)
11453         //      continue;
11454         // clip by each of the box planes formed from the projection matrix
11455         // if anything survives, we emit the decal
11456         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]);
11457         if (numpoints < 3)
11458                 return;
11459         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]);
11460         if (numpoints < 3)
11461                 return;
11462         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]);
11463         if (numpoints < 3)
11464                 return;
11465         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]);
11466         if (numpoints < 3)
11467                 return;
11468         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]);
11469         if (numpoints < 3)
11470                 return;
11471         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]);
11472         if (numpoints < 3)
11473                 return;
11474         // some part of the triangle survived, so we have to accept it...
11475         if (dynamic)
11476         {
11477                 // dynamic always uses the original triangle
11478                 numpoints = 3;
11479                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11480                 {
11481                         index = 3*e[cornerindex];
11482                         VectorCopy(vertex3f + index, v[cornerindex]);
11483                 }
11484         }
11485         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11486         {
11487                 // convert vertex positions to texcoords
11488                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11489                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11490                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11491                 // calculate distance fade from the projection origin
11492                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11493                 f = bound(0.0f, f, 1.0f);
11494                 c[cornerindex][0] = r * f;
11495                 c[cornerindex][1] = g * f;
11496                 c[cornerindex][2] = b * f;
11497                 c[cornerindex][3] = 1.0f;
11498                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11499         }
11500         if (dynamic)
11501                 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);
11502         else
11503                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11504                         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);
11505 }
11506 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, unsigned int decalsequence)
11507 {
11508         matrix4x4_t projection;
11509         decalsystem_t *decalsystem;
11510         qboolean dynamic;
11511         dp_model_t *model;
11512         const msurface_t *surface;
11513         const msurface_t *surfaces;
11514         const int *surfacelist;
11515         const texture_t *texture;
11516         int numtriangles;
11517         int numsurfacelist;
11518         int surfacelistindex;
11519         int surfaceindex;
11520         int triangleindex;
11521         float localorigin[3];
11522         float localnormal[3];
11523         float localmins[3];
11524         float localmaxs[3];
11525         float localsize;
11526         //float normal[3];
11527         float planes[6][4];
11528         float angles[3];
11529         bih_t *bih;
11530         int bih_triangles_count;
11531         int bih_triangles[256];
11532         int bih_surfaces[256];
11533
11534         decalsystem = &ent->decalsystem;
11535         model = ent->model;
11536         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11537         {
11538                 R_DecalSystem_Reset(&ent->decalsystem);
11539                 return;
11540         }
11541
11542         if (!model->brush.data_leafs && !cl_decals_models.integer)
11543         {
11544                 if (decalsystem->model)
11545                         R_DecalSystem_Reset(decalsystem);
11546                 return;
11547         }
11548
11549         if (decalsystem->model != model)
11550                 R_DecalSystem_Reset(decalsystem);
11551         decalsystem->model = model;
11552
11553         RSurf_ActiveModelEntity(ent, true, false, false);
11554
11555         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11556         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11557         VectorNormalize(localnormal);
11558         localsize = worldsize*rsurface.inversematrixscale;
11559         localmins[0] = localorigin[0] - localsize;
11560         localmins[1] = localorigin[1] - localsize;
11561         localmins[2] = localorigin[2] - localsize;
11562         localmaxs[0] = localorigin[0] + localsize;
11563         localmaxs[1] = localorigin[1] + localsize;
11564         localmaxs[2] = localorigin[2] + localsize;
11565
11566         //VectorCopy(localnormal, planes[4]);
11567         //VectorVectors(planes[4], planes[2], planes[0]);
11568         AnglesFromVectors(angles, localnormal, NULL, false);
11569         AngleVectors(angles, planes[0], planes[2], planes[4]);
11570         VectorNegate(planes[0], planes[1]);
11571         VectorNegate(planes[2], planes[3]);
11572         VectorNegate(planes[4], planes[5]);
11573         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11574         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11575         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11576         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11577         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11578         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11579
11580 #if 1
11581 // works
11582 {
11583         matrix4x4_t forwardprojection;
11584         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11585         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11586 }
11587 #else
11588 // broken
11589 {
11590         float projectionvector[4][3];
11591         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11592         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11593         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11594         projectionvector[0][0] = planes[0][0] * ilocalsize;
11595         projectionvector[0][1] = planes[1][0] * ilocalsize;
11596         projectionvector[0][2] = planes[2][0] * ilocalsize;
11597         projectionvector[1][0] = planes[0][1] * ilocalsize;
11598         projectionvector[1][1] = planes[1][1] * ilocalsize;
11599         projectionvector[1][2] = planes[2][1] * ilocalsize;
11600         projectionvector[2][0] = planes[0][2] * ilocalsize;
11601         projectionvector[2][1] = planes[1][2] * ilocalsize;
11602         projectionvector[2][2] = planes[2][2] * ilocalsize;
11603         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11604         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11605         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11606         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11607 }
11608 #endif
11609
11610         dynamic = model->surfmesh.isanimated;
11611         numsurfacelist = model->nummodelsurfaces;
11612         surfacelist = model->sortedmodelsurfaces;
11613         surfaces = model->data_surfaces;
11614
11615         bih = NULL;
11616         bih_triangles_count = -1;
11617         if(!dynamic)
11618         {
11619                 if(model->render_bih.numleafs)
11620                         bih = &model->render_bih;
11621                 else if(model->collision_bih.numleafs)
11622                         bih = &model->collision_bih;
11623         }
11624         if(bih)
11625                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11626         if(bih_triangles_count == 0)
11627                 return;
11628         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11629                 return;
11630         if(bih_triangles_count > 0)
11631         {
11632                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11633                 {
11634                         surfaceindex = bih_surfaces[triangleindex];
11635                         surface = surfaces + surfaceindex;
11636                         texture = surface->texture;
11637                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11638                                 continue;
11639                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11640                                 continue;
11641                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11642                 }
11643         }
11644         else
11645         {
11646                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11647                 {
11648                         surfaceindex = surfacelist[surfacelistindex];
11649                         surface = surfaces + surfaceindex;
11650                         // check cull box first because it rejects more than any other check
11651                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11652                                 continue;
11653                         // skip transparent surfaces
11654                         texture = surface->texture;
11655                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11656                                 continue;
11657                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11658                                 continue;
11659                         numtriangles = surface->num_triangles;
11660                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11661                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11662                 }
11663         }
11664 }
11665
11666 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11667 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, unsigned int decalsequence)
11668 {
11669         int renderentityindex;
11670         float worldmins[3];
11671         float worldmaxs[3];
11672         entity_render_t *ent;
11673
11674         if (!cl_decals_newsystem.integer)
11675                 return;
11676
11677         worldmins[0] = worldorigin[0] - worldsize;
11678         worldmins[1] = worldorigin[1] - worldsize;
11679         worldmins[2] = worldorigin[2] - worldsize;
11680         worldmaxs[0] = worldorigin[0] + worldsize;
11681         worldmaxs[1] = worldorigin[1] + worldsize;
11682         worldmaxs[2] = worldorigin[2] + worldsize;
11683
11684         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11685
11686         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11687         {
11688                 ent = r_refdef.scene.entities[renderentityindex];
11689                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11690                         continue;
11691
11692                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11693         }
11694 }
11695
11696 typedef struct r_decalsystem_splatqueue_s
11697 {
11698         vec3_t worldorigin;
11699         vec3_t worldnormal;
11700         float color[4];
11701         float tcrange[4];
11702         float worldsize;
11703         unsigned int decalsequence;
11704 }
11705 r_decalsystem_splatqueue_t;
11706
11707 int r_decalsystem_numqueued = 0;
11708 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11709
11710 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)
11711 {
11712         r_decalsystem_splatqueue_t *queue;
11713
11714         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11715                 return;
11716
11717         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11718         VectorCopy(worldorigin, queue->worldorigin);
11719         VectorCopy(worldnormal, queue->worldnormal);
11720         Vector4Set(queue->color, r, g, b, a);
11721         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11722         queue->worldsize = worldsize;
11723         queue->decalsequence = cl.decalsequence++;
11724 }
11725
11726 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11727 {
11728         int i;
11729         r_decalsystem_splatqueue_t *queue;
11730
11731         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11732                 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);
11733         r_decalsystem_numqueued = 0;
11734 }
11735
11736 extern cvar_t cl_decals_max;
11737 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11738 {
11739         int i;
11740         decalsystem_t *decalsystem = &ent->decalsystem;
11741         int numdecals;
11742         unsigned int killsequence;
11743         tridecal_t *decal;
11744         float frametime;
11745         float lifetime;
11746
11747         if (!decalsystem->numdecals)
11748                 return;
11749
11750         if (r_showsurfaces.integer)
11751                 return;
11752
11753         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11754         {
11755                 R_DecalSystem_Reset(decalsystem);
11756                 return;
11757         }
11758
11759         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11760         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11761
11762         if (decalsystem->lastupdatetime)
11763                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11764         else
11765                 frametime = 0;
11766         decalsystem->lastupdatetime = r_refdef.scene.time;
11767         numdecals = decalsystem->numdecals;
11768
11769         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11770         {
11771                 if (decal->color4f[0][3])
11772                 {
11773                         decal->lived += frametime;
11774                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11775                         {
11776                                 memset(decal, 0, sizeof(*decal));
11777                                 if (decalsystem->freedecal > i)
11778                                         decalsystem->freedecal = i;
11779                         }
11780                 }
11781         }
11782         decal = decalsystem->decals;
11783         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11784                 numdecals--;
11785
11786         // collapse the array by shuffling the tail decals into the gaps
11787         for (;;)
11788         {
11789                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11790                         decalsystem->freedecal++;
11791                 if (decalsystem->freedecal == numdecals)
11792                         break;
11793                 decal[decalsystem->freedecal] = decal[--numdecals];
11794         }
11795
11796         decalsystem->numdecals = numdecals;
11797
11798         if (numdecals <= 0)
11799         {
11800                 // if there are no decals left, reset decalsystem
11801                 R_DecalSystem_Reset(decalsystem);
11802         }
11803 }
11804
11805 extern skinframe_t *decalskinframe;
11806 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11807 {
11808         int i;
11809         decalsystem_t *decalsystem = &ent->decalsystem;
11810         int numdecals;
11811         tridecal_t *decal;
11812         float faderate;
11813         float alpha;
11814         float *v3f;
11815         float *c4f;
11816         float *t2f;
11817         const int *e;
11818         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11819         int numtris = 0;
11820
11821         numdecals = decalsystem->numdecals;
11822         if (!numdecals)
11823                 return;
11824
11825         if (r_showsurfaces.integer)
11826                 return;
11827
11828         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11829         {
11830                 R_DecalSystem_Reset(decalsystem);
11831                 return;
11832         }
11833
11834         // if the model is static it doesn't matter what value we give for
11835         // wantnormals and wanttangents, so this logic uses only rules applicable
11836         // to a model, knowing that they are meaningless otherwise
11837         RSurf_ActiveModelEntity(ent, false, false, false);
11838
11839         decalsystem->lastupdatetime = r_refdef.scene.time;
11840
11841         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11842
11843         // update vertex positions for animated models
11844         v3f = decalsystem->vertex3f;
11845         c4f = decalsystem->color4f;
11846         t2f = decalsystem->texcoord2f;
11847         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11848         {
11849                 if (!decal->color4f[0][3])
11850                         continue;
11851
11852                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11853                         continue;
11854
11855                 // skip backfaces
11856                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11857                         continue;
11858
11859                 // update color values for fading decals
11860                 if (decal->lived >= cl_decals_time.value)
11861                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11862                 else
11863                         alpha = 1.0f;
11864
11865                 c4f[ 0] = decal->color4f[0][0] * alpha;
11866                 c4f[ 1] = decal->color4f[0][1] * alpha;
11867                 c4f[ 2] = decal->color4f[0][2] * alpha;
11868                 c4f[ 3] = 1;
11869                 c4f[ 4] = decal->color4f[1][0] * alpha;
11870                 c4f[ 5] = decal->color4f[1][1] * alpha;
11871                 c4f[ 6] = decal->color4f[1][2] * alpha;
11872                 c4f[ 7] = 1;
11873                 c4f[ 8] = decal->color4f[2][0] * alpha;
11874                 c4f[ 9] = decal->color4f[2][1] * alpha;
11875                 c4f[10] = decal->color4f[2][2] * alpha;
11876                 c4f[11] = 1;
11877
11878                 t2f[0] = decal->texcoord2f[0][0];
11879                 t2f[1] = decal->texcoord2f[0][1];
11880                 t2f[2] = decal->texcoord2f[1][0];
11881                 t2f[3] = decal->texcoord2f[1][1];
11882                 t2f[4] = decal->texcoord2f[2][0];
11883                 t2f[5] = decal->texcoord2f[2][1];
11884
11885                 // update vertex positions for animated models
11886                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11887                 {
11888                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11889                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11890                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11891                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11892                 }
11893                 else
11894                 {
11895                         VectorCopy(decal->vertex3f[0], v3f);
11896                         VectorCopy(decal->vertex3f[1], v3f + 3);
11897                         VectorCopy(decal->vertex3f[2], v3f + 6);
11898                 }
11899
11900                 if (r_refdef.fogenabled)
11901                 {
11902                         alpha = RSurf_FogVertex(v3f);
11903                         VectorScale(c4f, alpha, c4f);
11904                         alpha = RSurf_FogVertex(v3f + 3);
11905                         VectorScale(c4f + 4, alpha, c4f + 4);
11906                         alpha = RSurf_FogVertex(v3f + 6);
11907                         VectorScale(c4f + 8, alpha, c4f + 8);
11908                 }
11909
11910                 v3f += 9;
11911                 c4f += 12;
11912                 t2f += 6;
11913                 numtris++;
11914         }
11915
11916         if (numtris > 0)
11917         {
11918                 r_refdef.stats[r_stat_drawndecals] += numtris;
11919
11920                 // now render the decals all at once
11921                 // (this assumes they all use one particle font texture!)
11922                 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);
11923 //              R_Mesh_ResetTextureState();
11924                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11925                 GL_DepthMask(false);
11926                 GL_DepthRange(0, 1);
11927                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11928                 GL_DepthTest(true);
11929                 GL_CullFace(GL_NONE);
11930                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11931                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11932                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11933         }
11934 }
11935
11936 static void R_DrawModelDecals(void)
11937 {
11938         int i, numdecals;
11939
11940         // fade faster when there are too many decals
11941         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11942         for (i = 0;i < r_refdef.scene.numentities;i++)
11943                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11944
11945         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11946         for (i = 0;i < r_refdef.scene.numentities;i++)
11947                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11948                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11949
11950         R_DecalSystem_ApplySplatEntitiesQueue();
11951
11952         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11953         for (i = 0;i < r_refdef.scene.numentities;i++)
11954                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11955
11956         r_refdef.stats[r_stat_totaldecals] += numdecals;
11957
11958         if (r_showsurfaces.integer)
11959                 return;
11960
11961         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11962
11963         for (i = 0;i < r_refdef.scene.numentities;i++)
11964         {
11965                 if (!r_refdef.viewcache.entityvisible[i])
11966                         continue;
11967                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11968                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11969         }
11970 }
11971
11972 extern cvar_t mod_collision_bih;
11973 static void R_DrawDebugModel(void)
11974 {
11975         entity_render_t *ent = rsurface.entity;
11976         int i, j, flagsmask;
11977         const msurface_t *surface;
11978         dp_model_t *model = ent->model;
11979
11980         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11981                 return;
11982
11983         if (r_showoverdraw.value > 0)
11984         {
11985                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11986                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11987                 R_SetupShader_Generic_NoTexture(false, false);
11988                 GL_DepthTest(false);
11989                 GL_DepthMask(false);
11990                 GL_DepthRange(0, 1);
11991                 GL_BlendFunc(GL_ONE, GL_ONE);
11992                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11993                 {
11994                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11995                                 continue;
11996                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11997                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11998                         {
11999                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12000                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12001                                 if (!rsurface.texture->currentlayers->depthmask)
12002                                         GL_Color(c, 0, 0, 1.0f);
12003                                 else if (ent == r_refdef.scene.worldentity)
12004                                         GL_Color(c, c, c, 1.0f);
12005                                 else
12006                                         GL_Color(0, c, 0, 1.0f);
12007                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12008                                 RSurf_DrawBatch();
12009                         }
12010                 }
12011                 rsurface.texture = NULL;
12012         }
12013
12014         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12015
12016 //      R_Mesh_ResetTextureState();
12017         R_SetupShader_Generic_NoTexture(false, false);
12018         GL_DepthRange(0, 1);
12019         GL_DepthTest(!r_showdisabledepthtest.integer);
12020         GL_DepthMask(false);
12021         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12022
12023         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12024         {
12025                 int triangleindex;
12026                 int bihleafindex;
12027                 qboolean cullbox = false;
12028                 const q3mbrush_t *brush;
12029                 const bih_t *bih = &model->collision_bih;
12030                 const bih_leaf_t *bihleaf;
12031                 float vertex3f[3][3];
12032                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12033                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12034                 {
12035                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12036                                 continue;
12037                         switch (bihleaf->type)
12038                         {
12039                         case BIH_BRUSH:
12040                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12041                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12042                                 {
12043                                         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);
12044                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12045                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12046                                 }
12047                                 break;
12048                         case BIH_COLLISIONTRIANGLE:
12049                                 triangleindex = bihleaf->itemindex;
12050                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12051                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12052                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12053                                 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);
12054                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12055                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12056                                 break;
12057                         case BIH_RENDERTRIANGLE:
12058                                 triangleindex = bihleaf->itemindex;
12059                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12060                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12061                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12062                                 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);
12063                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12064                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12065                                 break;
12066                         }
12067                 }
12068         }
12069
12070         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12071
12072 #ifndef USE_GLES2
12073         if (r_showtris.value > 0 && qglPolygonMode)
12074         {
12075                 if (r_showdisabledepthtest.integer)
12076                 {
12077                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12078                         GL_DepthMask(false);
12079                 }
12080                 else
12081                 {
12082                         GL_BlendFunc(GL_ONE, GL_ZERO);
12083                         GL_DepthMask(true);
12084                 }
12085                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12086                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12087                 {
12088                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12089                                 continue;
12090                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12091                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12092                         {
12093                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12094                                 if (!rsurface.texture->currentlayers->depthmask)
12095                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12096                                 else if (ent == r_refdef.scene.worldentity)
12097                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12098                                 else
12099                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12100                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12101                                 RSurf_DrawBatch();
12102                         }
12103                 }
12104                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12105                 rsurface.texture = NULL;
12106         }
12107
12108         if (r_shownormals.value != 0 && qglBegin)
12109         {
12110                 int l, k;
12111                 vec3_t v;
12112                 if (r_showdisabledepthtest.integer)
12113                 {
12114                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12115                         GL_DepthMask(false);
12116                 }
12117                 else
12118                 {
12119                         GL_BlendFunc(GL_ONE, GL_ZERO);
12120                         GL_DepthMask(true);
12121                 }
12122                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12123                 {
12124                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12125                                 continue;
12126                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12127                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12128                         {
12129                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12130                                 qglBegin(GL_LINES);
12131                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12132                                 {
12133                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12134                                         {
12135                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12136                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12137                                                 qglVertex3f(v[0], v[1], v[2]);
12138                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12139                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12140                                                 qglVertex3f(v[0], v[1], v[2]);
12141                                         }
12142                                 }
12143                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12144                                 {
12145                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12146                                         {
12147                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12148                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12149                                                 qglVertex3f(v[0], v[1], v[2]);
12150                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12151                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12152                                                 qglVertex3f(v[0], v[1], v[2]);
12153                                         }
12154                                 }
12155                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12156                                 {
12157                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12158                                         {
12159                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12160                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12161                                                 qglVertex3f(v[0], v[1], v[2]);
12162                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12163                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12164                                                 qglVertex3f(v[0], v[1], v[2]);
12165                                         }
12166                                 }
12167                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12168                                 {
12169                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12170                                         {
12171                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12172                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12173                                                 qglVertex3f(v[0], v[1], v[2]);
12174                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12175                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12176                                                 qglVertex3f(v[0], v[1], v[2]);
12177                                         }
12178                                 }
12179                                 qglEnd();
12180                                 CHECKGLERROR
12181                         }
12182                 }
12183                 rsurface.texture = NULL;
12184         }
12185 #endif
12186 }
12187
12188 int r_maxsurfacelist = 0;
12189 const msurface_t **r_surfacelist = NULL;
12190 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12191 {
12192         int i, j, endj, flagsmask;
12193         dp_model_t *model = ent->model;
12194         msurface_t *surfaces;
12195         unsigned char *update;
12196         int numsurfacelist = 0;
12197         if (model == NULL)
12198                 return;
12199
12200         if (r_maxsurfacelist < model->num_surfaces)
12201         {
12202                 r_maxsurfacelist = model->num_surfaces;
12203                 if (r_surfacelist)
12204                         Mem_Free((msurface_t **)r_surfacelist);
12205                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12206         }
12207
12208         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12209                 RSurf_ActiveModelEntity(ent, false, false, false);
12210         else if (prepass)
12211                 RSurf_ActiveModelEntity(ent, true, true, true);
12212         else if (depthonly)
12213         {
12214                 switch (vid.renderpath)
12215                 {
12216                 case RENDERPATH_GL20:
12217                 case RENDERPATH_D3D9:
12218                 case RENDERPATH_D3D10:
12219                 case RENDERPATH_D3D11:
12220                 case RENDERPATH_SOFT:
12221                 case RENDERPATH_GLES2:
12222                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12223                         break;
12224                 case RENDERPATH_GL11:
12225                 case RENDERPATH_GL13:
12226                 case RENDERPATH_GLES1:
12227                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12228                         break;
12229                 }
12230         }
12231         else
12232         {
12233                 switch (vid.renderpath)
12234                 {
12235                 case RENDERPATH_GL20:
12236                 case RENDERPATH_D3D9:
12237                 case RENDERPATH_D3D10:
12238                 case RENDERPATH_D3D11:
12239                 case RENDERPATH_SOFT:
12240                 case RENDERPATH_GLES2:
12241                         RSurf_ActiveModelEntity(ent, true, true, false);
12242                         break;
12243                 case RENDERPATH_GL11:
12244                 case RENDERPATH_GL13:
12245                 case RENDERPATH_GLES1:
12246                         RSurf_ActiveModelEntity(ent, true, false, false);
12247                         break;
12248                 }
12249         }
12250
12251         surfaces = model->data_surfaces;
12252         update = model->brushq1.lightmapupdateflags;
12253
12254         // update light styles
12255         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12256         {
12257                 model_brush_lightstyleinfo_t *style;
12258                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12259                 {
12260                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12261                         {
12262                                 int *list = style->surfacelist;
12263                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12264                                 for (j = 0;j < style->numsurfaces;j++)
12265                                         update[list[j]] = true;
12266                         }
12267                 }
12268         }
12269
12270         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12271
12272         if (debug)
12273         {
12274                 R_DrawDebugModel();
12275                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12276                 return;
12277         }
12278
12279         rsurface.lightmaptexture = NULL;
12280         rsurface.deluxemaptexture = NULL;
12281         rsurface.uselightmaptexture = false;
12282         rsurface.texture = NULL;
12283         rsurface.rtlight = NULL;
12284         numsurfacelist = 0;
12285         // add visible surfaces to draw list
12286         if (ent == r_refdef.scene.worldentity)
12287         {
12288                 // for the world entity, check surfacevisible
12289                 for (i = 0;i < model->nummodelsurfaces;i++)
12290                 {
12291                         j = model->sortedmodelsurfaces[i];
12292                         if (r_refdef.viewcache.world_surfacevisible[j])
12293                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12294                 }
12295         }
12296         else
12297         {
12298                 // add all surfaces
12299                 for (i = 0; i < model->nummodelsurfaces; i++)
12300                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12301         }
12302         // don't do anything if there were no surfaces
12303         if (!numsurfacelist)
12304         {
12305                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12306                 return;
12307         }
12308         // update lightmaps if needed
12309         if (update)
12310         {
12311                 int updated = 0;
12312                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12313                 {
12314                         if (update[j])
12315                         {
12316                                 updated++;
12317                                 R_BuildLightMap(ent, surfaces + j);
12318                         }
12319                 }
12320         }
12321
12322         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12323
12324         // add to stats if desired
12325         if (r_speeds.integer && !skysurfaces && !depthonly)
12326         {
12327                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12328                 for (j = 0;j < numsurfacelist;j++)
12329                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12330         }
12331
12332         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12333 }
12334
12335 void R_DebugLine(vec3_t start, vec3_t end)
12336 {
12337         dp_model_t *mod = CL_Mesh_UI();
12338         msurface_t *surf;
12339         int e0, e1, e2, e3;
12340         float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
12341         float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
12342         float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
12343         vec4_t w[2], s[2];
12344
12345         // transform to screen coords first
12346         Vector4Set(w[0], start[0], start[1], start[2], 1);
12347         Vector4Set(w[1], end[0], end[1], end[2], 1);
12348         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
12349         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
12350         x1 = s[0][0] * vid_conwidth.value / vid.width;
12351         y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
12352         x2 = s[1][0] * vid_conwidth.value / vid.width;
12353         y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
12354         //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
12355
12356         // add the line to the UI mesh for drawing later
12357
12358         // width is measured in real pixels
12359         if (fabs(x2 - x1) > fabs(y2 - y1))
12360         {
12361                 offsetx = 0;
12362                 offsety = 0.5f * width * vid_conheight.value / vid.height;
12363         }
12364         else
12365         {
12366                 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
12367                 offsety = 0;
12368         }
12369         surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_VERTEXCOLOR), true);
12370         e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
12371         e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
12372         e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
12373         e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
12374         Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
12375         Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
12376
12377 }
12378
12379
12380 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12381 {
12382         int q;
12383         static texture_t texture;
12384         static msurface_t surface;
12385         const msurface_t *surfacelist = &surface;
12386
12387         // fake enough texture and surface state to render this geometry
12388
12389         texture.update_lastrenderframe = -1; // regenerate this texture
12390         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12391         texture.basealpha = 1.0f;
12392         texture.currentskinframe = skinframe;
12393         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12394         texture.offsetmapping = OFFSETMAPPING_OFF;
12395         texture.offsetscale = 1;
12396         texture.specularscalemod = 1;
12397         texture.specularpowermod = 1;
12398         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12399         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12400         // JUST GREP FOR "specularscalemod = 1".
12401
12402         for (q = 0; q < 3; q++)
12403         {
12404                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12405                 texture.render_modellight_lightdir[q] = q == 2;
12406                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12407                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12408                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12409                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12410                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12411                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12412                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12413                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12414         }
12415         texture.currentalpha = 1.0f;
12416
12417         surface.texture = &texture;
12418         surface.num_triangles = numtriangles;
12419         surface.num_firsttriangle = firsttriangle;
12420         surface.num_vertices = numvertices;
12421         surface.num_firstvertex = firstvertex;
12422
12423         // now render it
12424         rsurface.texture = R_GetCurrentTexture(surface.texture);
12425         rsurface.lightmaptexture = NULL;
12426         rsurface.deluxemaptexture = NULL;
12427         rsurface.uselightmaptexture = false;
12428         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12429 }
12430
12431 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)
12432 {
12433         static msurface_t surface;
12434         const msurface_t *surfacelist = &surface;
12435
12436         // fake enough texture and surface state to render this geometry
12437         surface.texture = texture;
12438         surface.num_triangles = numtriangles;
12439         surface.num_firsttriangle = firsttriangle;
12440         surface.num_vertices = numvertices;
12441         surface.num_firstvertex = firstvertex;
12442
12443         // now render it
12444         rsurface.texture = R_GetCurrentTexture(surface.texture);
12445         rsurface.lightmaptexture = NULL;
12446         rsurface.deluxemaptexture = NULL;
12447         rsurface.uselightmaptexture = false;
12448         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12449 }