]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix the corona bug. The render bug only though.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 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!"};
67 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!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 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)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77 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"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 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)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84
85 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"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 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%)" };
98 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)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 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"};
102 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"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 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"};
105 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"};
106 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"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 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)"};
116 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)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 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"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 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"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 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"};
132 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"};
133
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 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."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 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."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 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."};
145 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."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 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"};
148 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"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 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"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 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
159 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
160
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169
170 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)"};
171 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"};
172
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176
177 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"};
178 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"};
179 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"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 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"};
183 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)"};
184 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)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 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)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 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)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 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)"};
193 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)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 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"};
196 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."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206
207 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)"};
208 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)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 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"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 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"};
215 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"};
216 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
217
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243
244 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"};
245
246 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"};
247
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251
252 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)"};
253 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)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 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"};
259
260 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."};
261
262 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)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {
265         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
269 };
270
271 extern cvar_t v_glslgamma_2d;
272
273 extern qboolean v_flipped_state;
274
275 r_framebufferstate_t r_fb;
276
277 /// shadow volume bsp struct with automatically growing nodes buffer
278 svbsp_t r_svbsp;
279
280 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
281
282 rtexture_t *r_texture_blanknormalmap;
283 rtexture_t *r_texture_white;
284 rtexture_t *r_texture_grey128;
285 rtexture_t *r_texture_black;
286 rtexture_t *r_texture_notexture;
287 rtexture_t *r_texture_whitecube;
288 rtexture_t *r_texture_normalizationcube;
289 rtexture_t *r_texture_fogattenuation;
290 rtexture_t *r_texture_fogheighttexture;
291 rtexture_t *r_texture_gammaramps;
292 unsigned int r_texture_gammaramps_serial;
293 //rtexture_t *r_texture_fogintensity;
294 rtexture_t *r_texture_reflectcube;
295
296 // TODO: hash lookups?
297 typedef struct cubemapinfo_s
298 {
299         char basename[64];
300         rtexture_t *texture;
301 }
302 cubemapinfo_t;
303
304 int r_texture_numcubemaps;
305 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
306
307 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
308 unsigned int r_numqueries;
309 unsigned int r_maxqueries;
310
311 typedef struct r_qwskincache_s
312 {
313         char name[MAX_QPATH];
314         skinframe_t *skinframe;
315 }
316 r_qwskincache_t;
317
318 static r_qwskincache_t *r_qwskincache;
319 static int r_qwskincache_size;
320
321 /// vertex coordinates for a quad that covers the screen exactly
322 extern const float r_screenvertex3f[12];
323 extern const float r_d3dscreenvertex3f[12];
324 const float r_screenvertex3f[12] =
325 {
326         0, 0, 0,
327         1, 0, 0,
328         1, 1, 0,
329         0, 1, 0
330 };
331 const float r_d3dscreenvertex3f[12] =
332 {
333         0, 1, 0,
334         1, 1, 0,
335         1, 0, 0,
336         0, 0, 0
337 };
338
339 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
340 {
341         int i;
342         for (i = 0;i < verts;i++)
343         {
344                 out[0] = in[0] * r;
345                 out[1] = in[1] * g;
346                 out[2] = in[2] * b;
347                 out[3] = in[3];
348                 in += 4;
349                 out += 4;
350         }
351 }
352
353 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
354 {
355         int i;
356         for (i = 0;i < verts;i++)
357         {
358                 out[0] = r;
359                 out[1] = g;
360                 out[2] = b;
361                 out[3] = a;
362                 out += 4;
363         }
364 }
365
366 // FIXME: move this to client?
367 void FOG_clear(void)
368 {
369         if (gamemode == GAME_NEHAHRA)
370         {
371                 Cvar_Set("gl_fogenable", "0");
372                 Cvar_Set("gl_fogdensity", "0.2");
373                 Cvar_Set("gl_fogred", "0.3");
374                 Cvar_Set("gl_foggreen", "0.3");
375                 Cvar_Set("gl_fogblue", "0.3");
376         }
377         r_refdef.fog_density = 0;
378         r_refdef.fog_red = 0;
379         r_refdef.fog_green = 0;
380         r_refdef.fog_blue = 0;
381         r_refdef.fog_alpha = 1;
382         r_refdef.fog_start = 0;
383         r_refdef.fog_end = 16384;
384         r_refdef.fog_height = 1<<30;
385         r_refdef.fog_fadedepth = 128;
386         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
387 }
388
389 static void R_BuildBlankTextures(void)
390 {
391         unsigned char data[4];
392         data[2] = 128; // normal X
393         data[1] = 128; // normal Y
394         data[0] = 255; // normal Z
395         data[3] = 255; // height
396         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 255;
398         data[1] = 255;
399         data[2] = 255;
400         data[3] = 255;
401         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 128;
403         data[1] = 128;
404         data[2] = 128;
405         data[3] = 255;
406         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407         data[0] = 0;
408         data[1] = 0;
409         data[2] = 0;
410         data[3] = 255;
411         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
412 }
413
414 static void R_BuildNoTexture(void)
415 {
416         int x, y;
417         unsigned char pix[16][16][4];
418         // this makes a light grey/dark grey checkerboard texture
419         for (y = 0;y < 16;y++)
420         {
421                 for (x = 0;x < 16;x++)
422                 {
423                         if ((y < 8) ^ (x < 8))
424                         {
425                                 pix[y][x][0] = 128;
426                                 pix[y][x][1] = 128;
427                                 pix[y][x][2] = 128;
428                                 pix[y][x][3] = 255;
429                         }
430                         else
431                         {
432                                 pix[y][x][0] = 64;
433                                 pix[y][x][1] = 64;
434                                 pix[y][x][2] = 64;
435                                 pix[y][x][3] = 255;
436                         }
437                 }
438         }
439         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
440 }
441
442 static void R_BuildWhiteCube(void)
443 {
444         unsigned char data[6*1*1*4];
445         memset(data, 255, sizeof(data));
446         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
447 }
448
449 static void R_BuildNormalizationCube(void)
450 {
451         int x, y, side;
452         vec3_t v;
453         vec_t s, t, intensity;
454 #define NORMSIZE 64
455         unsigned char *data;
456         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
457         for (side = 0;side < 6;side++)
458         {
459                 for (y = 0;y < NORMSIZE;y++)
460                 {
461                         for (x = 0;x < NORMSIZE;x++)
462                         {
463                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 switch(side)
466                                 {
467                                 default:
468                                 case 0:
469                                         v[0] = 1;
470                                         v[1] = -t;
471                                         v[2] = -s;
472                                         break;
473                                 case 1:
474                                         v[0] = -1;
475                                         v[1] = -t;
476                                         v[2] = s;
477                                         break;
478                                 case 2:
479                                         v[0] = s;
480                                         v[1] = 1;
481                                         v[2] = t;
482                                         break;
483                                 case 3:
484                                         v[0] = s;
485                                         v[1] = -1;
486                                         v[2] = -t;
487                                         break;
488                                 case 4:
489                                         v[0] = s;
490                                         v[1] = -t;
491                                         v[2] = 1;
492                                         break;
493                                 case 5:
494                                         v[0] = -s;
495                                         v[1] = -t;
496                                         v[2] = -1;
497                                         break;
498                                 }
499                                 intensity = 127.0f / sqrt(DotProduct(v, v));
500                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
501                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
502                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
503                                 data[((side*64+y)*64+x)*4+3] = 255;
504                         }
505                 }
506         }
507         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508         Mem_Free(data);
509 }
510
511 static void R_BuildFogTexture(void)
512 {
513         int x, b;
514 #define FOGWIDTH 256
515         unsigned char data1[FOGWIDTH][4];
516         //unsigned char data2[FOGWIDTH][4];
517         double d, r, alpha;
518
519         r_refdef.fogmasktable_start = r_refdef.fog_start;
520         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
521         r_refdef.fogmasktable_range = r_refdef.fogrange;
522         r_refdef.fogmasktable_density = r_refdef.fog_density;
523
524         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
525         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
526         {
527                 d = (x * r - r_refdef.fogmasktable_start);
528                 if(developer_extra.integer)
529                         Con_DPrintf("%f ", d);
530                 d = max(0, d);
531                 if (r_fog_exp2.integer)
532                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
533                 else
534                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
535                 if(developer_extra.integer)
536                         Con_DPrintf(" : %f ", alpha);
537                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
538                 if(developer_extra.integer)
539                         Con_DPrintf(" = %f\n", alpha);
540                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
541         }
542
543         for (x = 0;x < FOGWIDTH;x++)
544         {
545                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
546                 data1[x][0] = b;
547                 data1[x][1] = b;
548                 data1[x][2] = b;
549                 data1[x][3] = 255;
550                 //data2[x][0] = 255 - b;
551                 //data2[x][1] = 255 - b;
552                 //data2[x][2] = 255 - b;
553                 //data2[x][3] = 255;
554         }
555         if (r_texture_fogattenuation)
556         {
557                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559         }
560         else
561         {
562                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
563                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
564         }
565 }
566
567 static void R_BuildFogHeightTexture(void)
568 {
569         unsigned char *inpixels;
570         int size;
571         int x;
572         int y;
573         int j;
574         float c[4];
575         float f;
576         inpixels = NULL;
577         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
578         if (r_refdef.fogheighttexturename[0])
579                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
580         if (!inpixels)
581         {
582                 r_refdef.fog_height_tablesize = 0;
583                 if (r_texture_fogheighttexture)
584                         R_FreeTexture(r_texture_fogheighttexture);
585                 r_texture_fogheighttexture = NULL;
586                 if (r_refdef.fog_height_table2d)
587                         Mem_Free(r_refdef.fog_height_table2d);
588                 r_refdef.fog_height_table2d = NULL;
589                 if (r_refdef.fog_height_table1d)
590                         Mem_Free(r_refdef.fog_height_table1d);
591                 r_refdef.fog_height_table1d = NULL;
592                 return;
593         }
594         size = image_width;
595         r_refdef.fog_height_tablesize = size;
596         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
597         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
598         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
599         Mem_Free(inpixels);
600         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
601         // average fog color table accounting for every fog layer between a point
602         // and the camera.  (Note: attenuation is handled separately!)
603         for (y = 0;y < size;y++)
604         {
605                 for (x = 0;x < size;x++)
606                 {
607                         Vector4Clear(c);
608                         f = 0;
609                         if (x < y)
610                         {
611                                 for (j = x;j <= y;j++)
612                                 {
613                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
614                                         f++;
615                                 }
616                         }
617                         else
618                         {
619                                 for (j = x;j >= y;j--)
620                                 {
621                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
622                                         f++;
623                                 }
624                         }
625                         f = 1.0f / f;
626                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
627                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
630                 }
631         }
632         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
633 }
634
635 //=======================================================================================================================================================
636
637 static const char *builtinshaderstrings[] =
638 {
639 #include "shader_glsl.h"
640 0
641 };
642
643 const char *builtinhlslshaderstrings[] =
644 {
645 #include "shader_hlsl.h"
646 0
647 };
648
649 //=======================================================================================================================================================
650
651 typedef struct shaderpermutationinfo_s
652 {
653         const char *pretext;
654         const char *name;
655 }
656 shaderpermutationinfo_t;
657
658 typedef struct shadermodeinfo_s
659 {
660         const char *sourcebasename;
661         const char *extension;
662         const char **builtinshaderstrings;
663         const char *pretext;
664         const char *name;
665         char *filename;
666         char *builtinstring;
667         int builtincrc;
668 }
669 shadermodeinfo_t;
670
671 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
672 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
673 {
674         {"#define USEDIFFUSE\n", " diffuse"},
675         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
676         {"#define USEVIEWTINT\n", " viewtint"},
677         {"#define USECOLORMAPPING\n", " colormapping"},
678         {"#define USESATURATION\n", " saturation"},
679         {"#define USEFOGINSIDE\n", " foginside"},
680         {"#define USEFOGOUTSIDE\n", " fogoutside"},
681         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
682         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
683         {"#define USEGAMMARAMPS\n", " gammaramps"},
684         {"#define USECUBEFILTER\n", " cubefilter"},
685         {"#define USEGLOW\n", " glow"},
686         {"#define USEBLOOM\n", " bloom"},
687         {"#define USESPECULAR\n", " specular"},
688         {"#define USEPOSTPROCESSING\n", " postprocessing"},
689         {"#define USEREFLECTION\n", " reflection"},
690         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
691         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
692         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
693         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
694         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
695         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
696         {"#define USEALPHAKILL\n", " alphakill"},
697         {"#define USEREFLECTCUBE\n", " reflectcube"},
698         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
699         {"#define USEBOUNCEGRID\n", " bouncegrid"},
700         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
701         {"#define USETRIPPY\n", " trippy"},
702         {"#define USEDEPTHRGB\n", " depthrgb"},
703         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
704         {"#define USESKELETAL\n", " skeletal"},
705         {"#define USEOCCLUDE\n", " occlude"}
706 };
707
708 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
709 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
710 {
711         // SHADERLANGUAGE_GLSL
712         {
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730         },
731         // SHADERLANGUAGE_HLSL
732         {
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
750         },
751 };
752
753 struct r_glsl_permutation_s;
754 typedef struct r_glsl_permutation_s
755 {
756         /// hash lookup data
757         struct r_glsl_permutation_s *hashnext;
758         unsigned int mode;
759         dpuint64 permutation;
760
761         /// indicates if we have tried compiling this permutation already
762         qboolean compiled;
763         /// 0 if compilation failed
764         int program;
765         // texture units assigned to each detected uniform
766         int tex_Texture_First;
767         int tex_Texture_Second;
768         int tex_Texture_GammaRamps;
769         int tex_Texture_Normal;
770         int tex_Texture_Color;
771         int tex_Texture_Gloss;
772         int tex_Texture_Glow;
773         int tex_Texture_SecondaryNormal;
774         int tex_Texture_SecondaryColor;
775         int tex_Texture_SecondaryGloss;
776         int tex_Texture_SecondaryGlow;
777         int tex_Texture_Pants;
778         int tex_Texture_Shirt;
779         int tex_Texture_FogHeightTexture;
780         int tex_Texture_FogMask;
781         int tex_Texture_Lightmap;
782         int tex_Texture_Deluxemap;
783         int tex_Texture_Attenuation;
784         int tex_Texture_Cube;
785         int tex_Texture_Refraction;
786         int tex_Texture_Reflection;
787         int tex_Texture_ShadowMap2D;
788         int tex_Texture_CubeProjection;
789         int tex_Texture_ScreenNormalMap;
790         int tex_Texture_ScreenDiffuse;
791         int tex_Texture_ScreenSpecular;
792         int tex_Texture_ReflectMask;
793         int tex_Texture_ReflectCube;
794         int tex_Texture_BounceGrid;
795         /// locations of detected uniforms in program object, or -1 if not found
796         int loc_Texture_First;
797         int loc_Texture_Second;
798         int loc_Texture_GammaRamps;
799         int loc_Texture_Normal;
800         int loc_Texture_Color;
801         int loc_Texture_Gloss;
802         int loc_Texture_Glow;
803         int loc_Texture_SecondaryNormal;
804         int loc_Texture_SecondaryColor;
805         int loc_Texture_SecondaryGloss;
806         int loc_Texture_SecondaryGlow;
807         int loc_Texture_Pants;
808         int loc_Texture_Shirt;
809         int loc_Texture_FogHeightTexture;
810         int loc_Texture_FogMask;
811         int loc_Texture_Lightmap;
812         int loc_Texture_Deluxemap;
813         int loc_Texture_Attenuation;
814         int loc_Texture_Cube;
815         int loc_Texture_Refraction;
816         int loc_Texture_Reflection;
817         int loc_Texture_ShadowMap2D;
818         int loc_Texture_CubeProjection;
819         int loc_Texture_ScreenNormalMap;
820         int loc_Texture_ScreenDiffuse;
821         int loc_Texture_ScreenSpecular;
822         int loc_Texture_ReflectMask;
823         int loc_Texture_ReflectCube;
824         int loc_Texture_BounceGrid;
825         int loc_Alpha;
826         int loc_BloomBlur_Parameters;
827         int loc_ClientTime;
828         int loc_Color_Ambient;
829         int loc_Color_Diffuse;
830         int loc_Color_Specular;
831         int loc_Color_Glow;
832         int loc_Color_Pants;
833         int loc_Color_Shirt;
834         int loc_DeferredColor_Ambient;
835         int loc_DeferredColor_Diffuse;
836         int loc_DeferredColor_Specular;
837         int loc_DeferredMod_Diffuse;
838         int loc_DeferredMod_Specular;
839         int loc_DistortScaleRefractReflect;
840         int loc_EyePosition;
841         int loc_FogColor;
842         int loc_FogHeightFade;
843         int loc_FogPlane;
844         int loc_FogPlaneViewDist;
845         int loc_FogRangeRecip;
846         int loc_LightColor;
847         int loc_LightDir;
848         int loc_LightPosition;
849         int loc_OffsetMapping_ScaleSteps;
850         int loc_OffsetMapping_LodDistance;
851         int loc_OffsetMapping_Bias;
852         int loc_PixelSize;
853         int loc_ReflectColor;
854         int loc_ReflectFactor;
855         int loc_ReflectOffset;
856         int loc_RefractColor;
857         int loc_Saturation;
858         int loc_ScreenCenterRefractReflect;
859         int loc_ScreenScaleRefractReflect;
860         int loc_ScreenToDepth;
861         int loc_ShadowMap_Parameters;
862         int loc_ShadowMap_TextureScale;
863         int loc_SpecularPower;
864         int loc_Skeletal_Transform12;
865         int loc_UserVec1;
866         int loc_UserVec2;
867         int loc_UserVec3;
868         int loc_UserVec4;
869         int loc_ViewTintColor;
870         int loc_ViewToLight;
871         int loc_ModelToLight;
872         int loc_TexMatrix;
873         int loc_BackgroundTexMatrix;
874         int loc_ModelViewProjectionMatrix;
875         int loc_ModelViewMatrix;
876         int loc_PixelToScreenTexCoord;
877         int loc_ModelToReflectCube;
878         int loc_ShadowMapMatrix;
879         int loc_BloomColorSubtract;
880         int loc_NormalmapScrollBlend;
881         int loc_BounceGridMatrix;
882         int loc_BounceGridIntensity;
883         /// uniform block bindings
884         int ubibind_Skeletal_Transform12_UniformBlock;
885         /// uniform block indices
886         int ubiloc_Skeletal_Transform12_UniformBlock;
887 }
888 r_glsl_permutation_t;
889
890 #define SHADERPERMUTATION_HASHSIZE 256
891
892
893 // non-degradable "lightweight" shader parameters to keep the permutations simpler
894 // these can NOT degrade! only use for simple stuff
895 enum
896 {
897         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
898         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
899         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
900         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
903         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
904         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
905         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
906         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
907         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
908         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
909         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
910         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
911 };
912 #define SHADERSTATICPARMS_COUNT 14
913
914 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
915 static int shaderstaticparms_count = 0;
916
917 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
918 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
919
920 extern qboolean r_shadow_shadowmapsampler;
921 extern int r_shadow_shadowmappcf;
922 qboolean R_CompileShader_CheckStaticParms(void)
923 {
924         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
925         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
926         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
927
928         // detect all
929         if (r_glsl_saturation_redcompensate.integer)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
931         if (r_glsl_vertextextureblend_usebothalphas.integer)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
933         if (r_shadow_glossexact.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
935         if (r_glsl_postprocess.integer)
936         {
937                 if (r_glsl_postprocess_uservec1_enable.integer)
938                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
939                 if (r_glsl_postprocess_uservec2_enable.integer)
940                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
941                 if (r_glsl_postprocess_uservec3_enable.integer)
942                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
943                 if (r_glsl_postprocess_uservec4_enable.integer)
944                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
945         }
946         if (r_fxaa.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
948         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
950
951         if (r_shadow_shadowmapsampler)
952                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
953         if (r_shadow_shadowmappcf > 1)
954                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
955         else if (r_shadow_shadowmappcf)
956                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
957         if (r_celshading.integer)
958                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
959         if (r_celoutlines.integer)
960                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
961
962         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
963 }
964
965 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
966         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
967                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
968         else \
969                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
970 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
971 {
972         shaderstaticparms_count = 0;
973
974         // emit all
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
989 }
990
991 /// information about each possible shader permutation
992 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
993 /// currently selected permutation
994 r_glsl_permutation_t *r_glsl_permutation;
995 /// storage for permutations linked in the hash table
996 memexpandablearray_t r_glsl_permutationarray;
997
998 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
999 {
1000         //unsigned int hashdepth = 0;
1001         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1002         r_glsl_permutation_t *p;
1003         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1004         {
1005                 if (p->mode == mode && p->permutation == permutation)
1006                 {
1007                         //if (hashdepth > 10)
1008                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1009                         return p;
1010                 }
1011                 //hashdepth++;
1012         }
1013         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1014         p->mode = mode;
1015         p->permutation = permutation;
1016         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1017         r_glsl_permutationhash[mode][hashindex] = p;
1018         //if (hashdepth > 10)
1019         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1020         return p;
1021 }
1022
1023 static char *R_ShaderStrCat(const char **strings)
1024 {
1025         char *string, *s;
1026         const char **p = strings;
1027         const char *t;
1028         size_t len = 0;
1029         for (p = strings;(t = *p);p++)
1030                 len += strlen(t);
1031         len++;
1032         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1033         len = 0;
1034         for (p = strings;(t = *p);p++)
1035         {
1036                 len = strlen(t);
1037                 memcpy(s, t, len);
1038                 s += len;
1039         }
1040         *s = 0;
1041         return string;
1042 }
1043
1044 static char *R_ShaderStrCat(const char **strings);
1045 static void R_InitShaderModeInfo(void)
1046 {
1047         int i, language;
1048         shadermodeinfo_t *modeinfo;
1049         // 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)
1050         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1051         {
1052                 for (i = 0; i < SHADERMODE_COUNT; i++)
1053                 {
1054                         char filename[MAX_QPATH];
1055                         modeinfo = &shadermodeinfo[language][i];
1056                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1057                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1058                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1059                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1060                 }
1061         }
1062 }
1063
1064 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1065 {
1066         char *shaderstring;
1067         // if the mode has no filename we have to return the builtin string
1068         if (builtinonly || !modeinfo->filename)
1069                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1070         // note that FS_LoadFile appends a 0 byte to make it a valid string
1071         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1072         if (shaderstring)
1073         {
1074                 if (printfromdisknotice)
1075                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1076                 return shaderstring;
1077         }
1078         // fall back to builtinstring
1079         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127         // if we can do #version 120, we should (this adds the invariant keyword)
1128         else if(vid.support.glshaderversion >= 120)
1129         {
1130                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1131                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1132                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1133                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1134                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1135                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1136         }
1137         // GLES also adds several things from GLSL120
1138         switch(vid.renderpath)
1139         {
1140         case RENDERPATH_GLES2:
1141                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1142                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1143                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1144                 break;
1145         default:
1146                 break;
1147         }
1148
1149         // the first pretext is which type of shader to compile as
1150         // (later these will all be bound together as a program object)
1151         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1152         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1153         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1154
1155         // the second pretext is the mode (for example a light source)
1156         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1157         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1158         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1159         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1160
1161         // now add all the permutation pretexts
1162         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1163         {
1164                 if (permutation & (1ll<<i))
1165                 {
1166                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1167                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1170                 }
1171                 else
1172                 {
1173                         // keep line numbers correct
1174                         vertstrings_list[vertstrings_count++] = "\n";
1175                         geomstrings_list[geomstrings_count++] = "\n";
1176                         fragstrings_list[fragstrings_count++] = "\n";
1177                 }
1178         }
1179
1180         // add static parms
1181         R_CompileShader_AddStaticParms(mode, permutation);
1182         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1183         vertstrings_count += shaderstaticparms_count;
1184         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1185         geomstrings_count += shaderstaticparms_count;
1186         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1187         fragstrings_count += shaderstaticparms_count;
1188
1189         // now append the shader text itself
1190         vertstrings_list[vertstrings_count++] = sourcestring;
1191         geomstrings_list[geomstrings_count++] = sourcestring;
1192         fragstrings_list[fragstrings_count++] = sourcestring;
1193
1194         // compile the shader program
1195         if (vertstrings_count + geomstrings_count + fragstrings_count)
1196                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1197         if (p->program)
1198         {
1199                 CHECKGLERROR
1200                 qglUseProgram(p->program);CHECKGLERROR
1201                 // look up all the uniform variable names we care about, so we don't
1202                 // have to look them up every time we set them
1203
1204 #if 0
1205                 // debugging aid
1206                 {
1207                         GLint activeuniformindex = 0;
1208                         GLint numactiveuniforms = 0;
1209                         char uniformname[128];
1210                         GLsizei uniformnamelength = 0;
1211                         GLint uniformsize = 0;
1212                         GLenum uniformtype = 0;
1213                         memset(uniformname, 0, sizeof(uniformname));
1214                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1215                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1216                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1217                         {
1218                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1219                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1220                         }
1221                 }
1222 #endif
1223
1224                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1225                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1226                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1227                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1228                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1229                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1230                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1231                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1232                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1233                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1234                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1235                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1236                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1237                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1238                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1239                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1240                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1241                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1242                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1243                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1244                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1245                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1246                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1247                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1248                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1249                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1250                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1251                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1252                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1253                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1254                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1255                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1256                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1257                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1258                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1259                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1260                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1261                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1262                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1263                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1264                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1265                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1266                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1267                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1268                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1269                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1270                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1271                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1272                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1273                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1274                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1275                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1276                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1277                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1278                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1279                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1280                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1281                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1282                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1283                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1284                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1285                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1286                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1287                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1288                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1289                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1290                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1291                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1292                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1293                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1294                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1295                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1296                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1297                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1298                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1299                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1300                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1301                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1302                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1303                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1304                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1305                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1306                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1307                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1308                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1309                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1310                 // initialize the samplers to refer to the texture units we use
1311                 p->tex_Texture_First = -1;
1312                 p->tex_Texture_Second = -1;
1313                 p->tex_Texture_GammaRamps = -1;
1314                 p->tex_Texture_Normal = -1;
1315                 p->tex_Texture_Color = -1;
1316                 p->tex_Texture_Gloss = -1;
1317                 p->tex_Texture_Glow = -1;
1318                 p->tex_Texture_SecondaryNormal = -1;
1319                 p->tex_Texture_SecondaryColor = -1;
1320                 p->tex_Texture_SecondaryGloss = -1;
1321                 p->tex_Texture_SecondaryGlow = -1;
1322                 p->tex_Texture_Pants = -1;
1323                 p->tex_Texture_Shirt = -1;
1324                 p->tex_Texture_FogHeightTexture = -1;
1325                 p->tex_Texture_FogMask = -1;
1326                 p->tex_Texture_Lightmap = -1;
1327                 p->tex_Texture_Deluxemap = -1;
1328                 p->tex_Texture_Attenuation = -1;
1329                 p->tex_Texture_Cube = -1;
1330                 p->tex_Texture_Refraction = -1;
1331                 p->tex_Texture_Reflection = -1;
1332                 p->tex_Texture_ShadowMap2D = -1;
1333                 p->tex_Texture_CubeProjection = -1;
1334                 p->tex_Texture_ScreenNormalMap = -1;
1335                 p->tex_Texture_ScreenDiffuse = -1;
1336                 p->tex_Texture_ScreenSpecular = -1;
1337                 p->tex_Texture_ReflectMask = -1;
1338                 p->tex_Texture_ReflectCube = -1;
1339                 p->tex_Texture_BounceGrid = -1;
1340                 // bind the texture samplers in use
1341                 sampler = 0;
1342                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1343                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1344                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1345                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1346                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1347                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1348                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1349                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1353                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1354                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1355                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1356                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1357                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1358                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1359                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1360                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1361                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1362                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1363                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1364                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1365                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1368                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1370                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1371                 // get the uniform block indices so we can bind them
1372 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1373                 if (vid.support.arb_uniform_buffer_object)
1374                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1375                 else
1376 #endif
1377                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1378                 // clear the uniform block bindings
1379                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1380                 // bind the uniform blocks in use
1381                 ubibind = 0;
1382 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1383                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1384 #endif
1385                 // we're done compiling and setting up the shader, at least until it is used
1386                 CHECKGLERROR
1387                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1388         }
1389         else
1390                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1391
1392         // free the strings
1393         if (sourcestring)
1394                 Mem_Free(sourcestring);
1395 }
1396
1397 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1398 {
1399         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1400         if (r_glsl_permutation != perm)
1401         {
1402                 r_glsl_permutation = perm;
1403                 if (!r_glsl_permutation->program)
1404                 {
1405                         if (!r_glsl_permutation->compiled)
1406                         {
1407                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1408                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1409                         }
1410                         if (!r_glsl_permutation->program)
1411                         {
1412                                 // remove features until we find a valid permutation
1413                                 int i;
1414                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1415                                 {
1416                                         // reduce i more quickly whenever it would not remove any bits
1417                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1418                                         if (!(permutation & j))
1419                                                 continue;
1420                                         permutation -= j;
1421                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422                                         if (!r_glsl_permutation->compiled)
1423                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1424                                         if (r_glsl_permutation->program)
1425                                                 break;
1426                                 }
1427                                 if (i >= SHADERPERMUTATION_COUNT)
1428                                 {
1429                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1430                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1431                                         qglUseProgram(0);CHECKGLERROR
1432                                         return; // no bit left to clear, entire mode is broken
1433                                 }
1434                         }
1435                 }
1436                 CHECKGLERROR
1437                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1438         }
1439         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1440         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1441         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1442         CHECKGLERROR
1443 }
1444
1445 #ifdef SUPPORTD3D
1446
1447 #ifdef SUPPORTD3D
1448 #include <d3d9.h>
1449 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1450 extern D3DCAPS9 vid_d3d9caps;
1451 #endif
1452
1453 struct r_hlsl_permutation_s;
1454 typedef struct r_hlsl_permutation_s
1455 {
1456         /// hash lookup data
1457         struct r_hlsl_permutation_s *hashnext;
1458         unsigned int mode;
1459         dpuint64 permutation;
1460
1461         /// indicates if we have tried compiling this permutation already
1462         qboolean compiled;
1463         /// NULL if compilation failed
1464         IDirect3DVertexShader9 *vertexshader;
1465         IDirect3DPixelShader9 *pixelshader;
1466 }
1467 r_hlsl_permutation_t;
1468
1469 typedef enum D3DVSREGISTER_e
1470 {
1471         D3DVSREGISTER_TexMatrix = 0, // float4x4
1472         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1473         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1474         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1475         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1476         D3DVSREGISTER_ModelToLight = 20, // float4x4
1477         D3DVSREGISTER_EyePosition = 24,
1478         D3DVSREGISTER_FogPlane = 25,
1479         D3DVSREGISTER_LightDir = 26,
1480         D3DVSREGISTER_LightPosition = 27,
1481 }
1482 D3DVSREGISTER_t;
1483
1484 typedef enum D3DPSREGISTER_e
1485 {
1486         D3DPSREGISTER_Alpha = 0,
1487         D3DPSREGISTER_BloomBlur_Parameters = 1,
1488         D3DPSREGISTER_ClientTime = 2,
1489         D3DPSREGISTER_Color_Ambient = 3,
1490         D3DPSREGISTER_Color_Diffuse = 4,
1491         D3DPSREGISTER_Color_Specular = 5,
1492         D3DPSREGISTER_Color_Glow = 6,
1493         D3DPSREGISTER_Color_Pants = 7,
1494         D3DPSREGISTER_Color_Shirt = 8,
1495         D3DPSREGISTER_DeferredColor_Ambient = 9,
1496         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1497         D3DPSREGISTER_DeferredColor_Specular = 11,
1498         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1499         D3DPSREGISTER_DeferredMod_Specular = 13,
1500         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1501         D3DPSREGISTER_EyePosition = 15, // unused
1502         D3DPSREGISTER_FogColor = 16,
1503         D3DPSREGISTER_FogHeightFade = 17,
1504         D3DPSREGISTER_FogPlane = 18,
1505         D3DPSREGISTER_FogPlaneViewDist = 19,
1506         D3DPSREGISTER_FogRangeRecip = 20,
1507         D3DPSREGISTER_LightColor = 21,
1508         D3DPSREGISTER_LightDir = 22, // unused
1509         D3DPSREGISTER_LightPosition = 23,
1510         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1511         D3DPSREGISTER_PixelSize = 25,
1512         D3DPSREGISTER_ReflectColor = 26,
1513         D3DPSREGISTER_ReflectFactor = 27,
1514         D3DPSREGISTER_ReflectOffset = 28,
1515         D3DPSREGISTER_RefractColor = 29,
1516         D3DPSREGISTER_Saturation = 30,
1517         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1518         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1519         D3DPSREGISTER_ScreenToDepth = 33,
1520         D3DPSREGISTER_ShadowMap_Parameters = 34,
1521         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1522         D3DPSREGISTER_SpecularPower = 36,
1523         D3DPSREGISTER_UserVec1 = 37,
1524         D3DPSREGISTER_UserVec2 = 38,
1525         D3DPSREGISTER_UserVec3 = 39,
1526         D3DPSREGISTER_UserVec4 = 40,
1527         D3DPSREGISTER_ViewTintColor = 41,
1528         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1529         D3DPSREGISTER_BloomColorSubtract = 43,
1530         D3DPSREGISTER_ViewToLight = 44, // float4x4
1531         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1532         D3DPSREGISTER_NormalmapScrollBlend = 52,
1533         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1534         D3DPSREGISTER_OffsetMapping_Bias = 54,
1535         // next at 54
1536 }
1537 D3DPSREGISTER_t;
1538
1539 /// information about each possible shader permutation
1540 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1541 /// currently selected permutation
1542 r_hlsl_permutation_t *r_hlsl_permutation;
1543 /// storage for permutations linked in the hash table
1544 memexpandablearray_t r_hlsl_permutationarray;
1545
1546 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1547 {
1548         //unsigned int hashdepth = 0;
1549         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1550         r_hlsl_permutation_t *p;
1551         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1552         {
1553                 if (p->mode == mode && p->permutation == permutation)
1554                 {
1555                         //if (hashdepth > 10)
1556                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1557                         return p;
1558                 }
1559                 //hashdepth++;
1560         }
1561         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1562         p->mode = mode;
1563         p->permutation = permutation;
1564         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1565         r_hlsl_permutationhash[mode][hashindex] = p;
1566         //if (hashdepth > 10)
1567         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1568         return p;
1569 }
1570
1571 #include <d3dx9.h>
1572 //#include <d3dx9shader.h>
1573 //#include <d3dx9mesh.h>
1574
1575 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1576 {
1577         DWORD *vsbin = NULL;
1578         DWORD *psbin = NULL;
1579         fs_offset_t vsbinsize;
1580         fs_offset_t psbinsize;
1581 //      IDirect3DVertexShader9 *vs = NULL;
1582 //      IDirect3DPixelShader9 *ps = NULL;
1583         ID3DXBuffer *vslog = NULL;
1584         ID3DXBuffer *vsbuffer = NULL;
1585         ID3DXConstantTable *vsconstanttable = NULL;
1586         ID3DXBuffer *pslog = NULL;
1587         ID3DXBuffer *psbuffer = NULL;
1588         ID3DXConstantTable *psconstanttable = NULL;
1589         int vsresult = 0;
1590         int psresult = 0;
1591         char temp[MAX_INPUTLINE];
1592         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1593         char vabuf[1024];
1594         qboolean debugshader = gl_paranoid.integer != 0;
1595         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (!debugshader)
1598         {
1599                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1600                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1601         }
1602         if ((!vsbin && vertstring) || (!psbin && fragstring))
1603         {
1604                 const char* dllnames_d3dx9 [] =
1605                 {
1606                         "d3dx9_43.dll",
1607                         "d3dx9_42.dll",
1608                         "d3dx9_41.dll",
1609                         "d3dx9_40.dll",
1610                         "d3dx9_39.dll",
1611                         "d3dx9_38.dll",
1612                         "d3dx9_37.dll",
1613                         "d3dx9_36.dll",
1614                         "d3dx9_35.dll",
1615                         "d3dx9_34.dll",
1616                         "d3dx9_33.dll",
1617                         "d3dx9_32.dll",
1618                         "d3dx9_31.dll",
1619                         "d3dx9_30.dll",
1620                         "d3dx9_29.dll",
1621                         "d3dx9_28.dll",
1622                         "d3dx9_27.dll",
1623                         "d3dx9_26.dll",
1624                         "d3dx9_25.dll",
1625                         "d3dx9_24.dll",
1626                         NULL
1627                 };
1628                 dllhandle_t d3dx9_dll = NULL;
1629                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1630                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1631                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1632                 dllfunction_t d3dx9_dllfuncs[] =
1633                 {
1634                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1635                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1636                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1637                         {NULL, NULL}
1638                 };
1639                 // 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...
1640 #ifndef ID3DXBuffer_GetBufferPointer
1641 #if !defined(__cplusplus) || defined(CINTERFACE)
1642 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1643 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1644 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1645 #else
1646 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1647 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1648 #define ID3DXBuffer_Release(p)            (p)->Release()
1649 #endif
1650 #endif
1651                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1652                 {
1653                         DWORD shaderflags = 0;
1654                         if (debugshader)
1655                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1656                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1657                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1658                         if (vertstring && vertstring[0])
1659                         {
1660                                 if (debugshader)
1661                                 {
1662                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1663                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1664                                 }
1665                                 else
1666                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1667                                 if (vsbuffer)
1668                                 {
1669                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1670                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1671                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1672                                         ID3DXBuffer_Release(vsbuffer);
1673                                 }
1674                                 if (vslog)
1675                                 {
1676                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1677                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1678                                         ID3DXBuffer_Release(vslog);
1679                                 }
1680                         }
1681                         if (fragstring && fragstring[0])
1682                         {
1683                                 if (debugshader)
1684                                 {
1685                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1686                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1687                                 }
1688                                 else
1689                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1690                                 if (psbuffer)
1691                                 {
1692                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1693                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1694                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1695                                         ID3DXBuffer_Release(psbuffer);
1696                                 }
1697                                 if (pslog)
1698                                 {
1699                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1700                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1701                                         ID3DXBuffer_Release(pslog);
1702                                 }
1703                         }
1704                         Sys_UnloadLibrary(&d3dx9_dll);
1705                 }
1706                 else
1707                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1708         }
1709         if (vsbin && psbin)
1710         {
1711                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1712                 if (FAILED(vsresult))
1713                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1714                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1715                 if (FAILED(psresult))
1716                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1717         }
1718         // free the shader data
1719         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1720         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1721 }
1722
1723 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1724 {
1725         int i;
1726         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1727         int vertstring_length = 0;
1728         int geomstring_length = 0;
1729         int fragstring_length = 0;
1730         char *t;
1731         char *sourcestring;
1732         char *vertstring, *geomstring, *fragstring;
1733         char permutationname[256];
1734         char cachename[256];
1735         int vertstrings_count = 0;
1736         int geomstrings_count = 0;
1737         int fragstrings_count = 0;
1738         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741
1742         if (p->compiled)
1743                 return;
1744         p->compiled = true;
1745         p->vertexshader = NULL;
1746         p->pixelshader = NULL;
1747
1748         permutationname[0] = 0;
1749         cachename[0] = 0;
1750         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1751
1752         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1753         strlcat(cachename, "hlsl/", sizeof(cachename));
1754
1755         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1756         vertstrings_count = 0;
1757         geomstrings_count = 0;
1758         fragstrings_count = 0;
1759         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1760         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1761         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1762
1763         // the first pretext is which type of shader to compile as
1764         // (later these will all be bound together as a program object)
1765         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1766         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1767         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1768
1769         // the second pretext is the mode (for example a light source)
1770         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1771         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1772         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1773         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1774         strlcat(cachename, modeinfo->name, sizeof(cachename));
1775
1776         // now add all the permutation pretexts
1777         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778         {
1779                 if (permutation & (1ll<<i))
1780                 {
1781                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1782                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1785                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1786                 }
1787                 else
1788                 {
1789                         // keep line numbers correct
1790                         vertstrings_list[vertstrings_count++] = "\n";
1791                         geomstrings_list[geomstrings_count++] = "\n";
1792                         fragstrings_list[fragstrings_count++] = "\n";
1793                 }
1794         }
1795
1796         // add static parms
1797         R_CompileShader_AddStaticParms(mode, permutation);
1798         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1799         vertstrings_count += shaderstaticparms_count;
1800         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1801         geomstrings_count += shaderstaticparms_count;
1802         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1803         fragstrings_count += shaderstaticparms_count;
1804
1805         // replace spaces in the cachename with _ characters
1806         for (i = 0;cachename[i];i++)
1807                 if (cachename[i] == ' ')
1808                         cachename[i] = '_';
1809
1810         // now append the shader text itself
1811         vertstrings_list[vertstrings_count++] = sourcestring;
1812         geomstrings_list[geomstrings_count++] = sourcestring;
1813         fragstrings_list[fragstrings_count++] = sourcestring;
1814
1815         vertstring_length = 0;
1816         for (i = 0;i < vertstrings_count;i++)
1817                 vertstring_length += (int)strlen(vertstrings_list[i]);
1818         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1819         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1820                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1821
1822         geomstring_length = 0;
1823         for (i = 0;i < geomstrings_count;i++)
1824                 geomstring_length += (int)strlen(geomstrings_list[i]);
1825         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1826         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1827                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1828
1829         fragstring_length = 0;
1830         for (i = 0;i < fragstrings_count;i++)
1831                 fragstring_length += (int)strlen(fragstrings_list[i]);
1832         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1833         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1834                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1835
1836         // try to load the cached shader, or generate one
1837         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1838
1839         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1840                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1841         else
1842                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1843
1844         // free the strings
1845         if (vertstring)
1846                 Mem_Free(vertstring);
1847         if (geomstring)
1848                 Mem_Free(geomstring);
1849         if (fragstring)
1850                 Mem_Free(fragstring);
1851         if (sourcestring)
1852                 Mem_Free(sourcestring);
1853 }
1854
1855 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 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);}
1858 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);}
1859 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);}
1860 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);}
1861
1862 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1863 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1864 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);}
1865 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);}
1866 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);}
1867 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);}
1868
1869 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1870 {
1871         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1872         if (r_hlsl_permutation != perm)
1873         {
1874                 r_hlsl_permutation = perm;
1875                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876                 {
1877                         if (!r_hlsl_permutation->compiled)
1878                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1879                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1880                         {
1881                                 // remove features until we find a valid permutation
1882                                 int i;
1883                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                                 {
1885                                         // reduce i more quickly whenever it would not remove any bits
1886                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1887                                         if (!(permutation & j))
1888                                                 continue;
1889                                         permutation -= j;
1890                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891                                         if (!r_hlsl_permutation->compiled)
1892                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1893                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1894                                                 break;
1895                                 }
1896                                 if (i >= SHADERPERMUTATION_COUNT)
1897                                 {
1898                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1899                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1900                                         return; // no bit left to clear, entire mode is broken
1901                                 }
1902                         }
1903                 }
1904                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1905                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1906         }
1907         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1909         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1910 }
1911 #endif
1912
1913 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1914 {
1915         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1916         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1918         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1919 }
1920
1921 void R_GLSL_Restart_f(void)
1922 {
1923         unsigned int i, limit;
1924         switch(vid.renderpath)
1925         {
1926         case RENDERPATH_D3D9:
1927 #ifdef SUPPORTD3D
1928                 {
1929                         r_hlsl_permutation_t *p;
1930                         r_hlsl_permutation = NULL;
1931                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1932                         for (i = 0;i < limit;i++)
1933                         {
1934                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1935                                 {
1936                                         if (p->vertexshader)
1937                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1938                                         if (p->pixelshader)
1939                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1940                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1941                                 }
1942                         }
1943                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1944                 }
1945 #endif
1946                 break;
1947         case RENDERPATH_D3D10:
1948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949                 break;
1950         case RENDERPATH_D3D11:
1951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_GLES2:
1955                 {
1956                         r_glsl_permutation_t *p;
1957                         r_glsl_permutation = NULL;
1958                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1959                         for (i = 0;i < limit;i++)
1960                         {
1961                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1962                                 {
1963                                         GL_Backend_FreeProgram(p->program);
1964                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1965                                 }
1966                         }
1967                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1968                 }
1969                 break;
1970         case RENDERPATH_GL11:
1971         case RENDERPATH_GL13:
1972         case RENDERPATH_GLES1:
1973                 break;
1974         case RENDERPATH_SOFT:
1975                 break;
1976         }
1977 }
1978
1979 static void R_GLSL_DumpShader_f(void)
1980 {
1981         int i, language, mode, dupe;
1982         char *text;
1983         shadermodeinfo_t *modeinfo;
1984         qfile_t *file;
1985
1986         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1987         {
1988                 modeinfo = shadermodeinfo[language];
1989                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1990                 {
1991                         // don't dump the same file multiple times (most or all shaders come from the same file)
1992                         for (dupe = mode - 1;dupe >= 0;dupe--)
1993                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1994                                         break;
1995                         if (dupe >= 0)
1996                                 continue;
1997                         text = modeinfo[mode].builtinstring;
1998                         if (!text)
1999                                 continue;
2000                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2001                         if (file)
2002                         {
2003                                 FS_Print(file, "/* The engine may define the following macros:\n");
2004                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2005                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2006                                         FS_Print(file, modeinfo[i].pretext);
2007                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2008                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2009                                 FS_Print(file, "*/\n");
2010                                 FS_Print(file, text);
2011                                 FS_Close(file);
2012                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2013                         }
2014                         else
2015                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2016                 }
2017         }
2018 }
2019
2020 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2021 {
2022         dpuint64 permutation = 0;
2023         if (r_trippy.integer && !notrippy)
2024                 permutation |= SHADERPERMUTATION_TRIPPY;
2025         permutation |= SHADERPERMUTATION_VIEWTINT;
2026         if (first)
2027                 permutation |= SHADERPERMUTATION_DIFFUSE;
2028         if (second)
2029                 permutation |= SHADERPERMUTATION_SPECULAR;
2030         if (texturemode == GL_MODULATE)
2031                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2032         else if (texturemode == GL_ADD)
2033                 permutation |= SHADERPERMUTATION_GLOW;
2034         else if (texturemode == GL_DECAL)
2035                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2036         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2037                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2038         if (suppresstexalpha)
2039                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2040         if (!second)
2041                 texturemode = GL_MODULATE;
2042         if (vid.allowalphatocoverage)
2043                 GL_AlphaToCoverage(false);
2044         switch (vid.renderpath)
2045         {
2046         case RENDERPATH_D3D9:
2047 #ifdef SUPPORTD3D
2048                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2049                 R_Mesh_TexBind(GL20TU_FIRST , first );
2050                 R_Mesh_TexBind(GL20TU_SECOND, second);
2051                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2052                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2053 #endif
2054                 break;
2055         case RENDERPATH_D3D10:
2056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057                 break;
2058         case RENDERPATH_D3D11:
2059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060                 break;
2061         case RENDERPATH_GL20:
2062         case RENDERPATH_GLES2:
2063                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2064                 if (r_glsl_permutation->tex_Texture_First >= 0)
2065                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2066                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2067                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2068                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2069                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2070                 break;
2071         case RENDERPATH_GL13:
2072         case RENDERPATH_GLES1:
2073                 R_Mesh_TexBind(0, first );
2074                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2075                 R_Mesh_TexMatrix(0, NULL);
2076                 R_Mesh_TexBind(1, second);
2077                 if (second)
2078                 {
2079                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2080                         R_Mesh_TexMatrix(1, NULL);
2081                 }
2082                 break;
2083         case RENDERPATH_GL11:
2084                 R_Mesh_TexBind(0, first );
2085                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2086                 R_Mesh_TexMatrix(0, NULL);
2087                 break;
2088         case RENDERPATH_SOFT:
2089                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2090                 R_Mesh_TexBind(GL20TU_FIRST , first );
2091                 R_Mesh_TexBind(GL20TU_SECOND, second);
2092                 break;
2093         }
2094 }
2095
2096 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2097 {
2098         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2099 }
2100
2101 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2102 {
2103         dpuint64 permutation = 0;
2104         if (r_trippy.integer && !notrippy)
2105                 permutation |= SHADERPERMUTATION_TRIPPY;
2106         if (depthrgb)
2107                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2108         if (skeletal)
2109                 permutation |= SHADERPERMUTATION_SKELETAL;
2110
2111         if (vid.allowalphatocoverage)
2112                 GL_AlphaToCoverage(false);
2113         switch (vid.renderpath)
2114         {
2115         case RENDERPATH_D3D9:
2116 #ifdef SUPPORTD3D
2117                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2118 #endif
2119                 break;
2120         case RENDERPATH_D3D10:
2121                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2122                 break;
2123         case RENDERPATH_D3D11:
2124                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2125                 break;
2126         case RENDERPATH_GL20:
2127         case RENDERPATH_GLES2:
2128                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2130                 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);
2131 #endif
2132                 break;
2133         case RENDERPATH_GL13:
2134         case RENDERPATH_GLES1:
2135                 R_Mesh_TexBind(0, 0);
2136                 R_Mesh_TexBind(1, 0);
2137                 break;
2138         case RENDERPATH_GL11:
2139                 R_Mesh_TexBind(0, 0);
2140                 break;
2141         case RENDERPATH_SOFT:
2142                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2143                 break;
2144         }
2145 }
2146
2147 extern qboolean r_shadow_usingdeferredprepass;
2148 extern rtexture_t *r_shadow_attenuationgradienttexture;
2149 extern rtexture_t *r_shadow_attenuation2dtexture;
2150 extern rtexture_t *r_shadow_attenuation3dtexture;
2151 extern qboolean r_shadow_usingshadowmap2d;
2152 extern qboolean r_shadow_usingshadowmaportho;
2153 extern float r_shadow_modelshadowmap_texturescale[4];
2154 extern float r_shadow_modelshadowmap_parameters[4];
2155 extern float r_shadow_lightshadowmap_texturescale[4];
2156 extern float r_shadow_lightshadowmap_parameters[4];
2157 extern qboolean r_shadow_shadowmapvsdct;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2160 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2161 extern matrix4x4_t r_shadow_shadowmapmatrix;
2162 extern int r_shadow_prepass_width;
2163 extern int r_shadow_prepass_height;
2164 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2165 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2166 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2167 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2168
2169 #define BLENDFUNC_ALLOWS_COLORMOD      1
2170 #define BLENDFUNC_ALLOWS_FOG           2
2171 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2172 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2173 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2174 static int R_BlendFuncFlags(int src, int dst)
2175 {
2176         int r = 0;
2177
2178         // a blendfunc allows colormod if:
2179         // a) it can never keep the destination pixel invariant, or
2180         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2181         // this is to prevent unintended side effects from colormod
2182
2183         // a blendfunc allows fog if:
2184         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2185         // this is to prevent unintended side effects from fog
2186
2187         // these checks are the output of fogeval.pl
2188
2189         r |= BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2198         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2199         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2202         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2203         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2209         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2211
2212         return r;
2213 }
2214
2215 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)
2216 {
2217         // select a permutation of the lighting shader appropriate to this
2218         // combination of texture, entity, light source, and fogging, only use the
2219         // minimum features necessary to avoid wasting rendering time in the
2220         // fragment shader on features that are not being used
2221         dpuint64 permutation = 0;
2222         unsigned int mode = 0;
2223         int blendfuncflags;
2224         texture_t *t = rsurface.texture;
2225         float m16f[16];
2226         matrix4x4_t tempmatrix;
2227         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2228         if (r_trippy.integer && !notrippy)
2229                 permutation |= SHADERPERMUTATION_TRIPPY;
2230         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2231                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2232         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2233                 permutation |= SHADERPERMUTATION_OCCLUDE;
2234         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2235                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2236         if (rsurfacepass == RSURFPASS_BACKGROUND)
2237         {
2238                 // distorted background
2239                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2240                 {
2241                         mode = SHADERMODE_WATER;
2242                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2243                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2244                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2245                         {
2246                                 // this is the right thing to do for wateralpha
2247                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2248                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2249                         }
2250                         else
2251                         {
2252                                 // this is the right thing to do for entity alpha
2253                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                         }
2256                 }
2257                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2258                 {
2259                         mode = SHADERMODE_REFRACTION;
2260                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2261                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2262                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264                 }
2265                 else
2266                 {
2267                         mode = SHADERMODE_GENERIC;
2268                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2269                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2270                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271                 }
2272                 if (vid.allowalphatocoverage)
2273                         GL_AlphaToCoverage(false);
2274         }
2275         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2276         {
2277                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2278                 {
2279                         switch(t->offsetmapping)
2280                         {
2281                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2282                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_OFF: break;
2285                         }
2286                 }
2287                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2288                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2289                 // normalmap (deferred prepass), may use alpha test on diffuse
2290                 mode = SHADERMODE_DEFERREDGEOMETRY;
2291                 GL_BlendFunc(GL_ONE, GL_ZERO);
2292                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2293                 if (vid.allowalphatocoverage)
2294                         GL_AlphaToCoverage(false);
2295         }
2296         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2297         {
2298                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2299                 {
2300                         switch(t->offsetmapping)
2301                         {
2302                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2303                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305                         case OFFSETMAPPING_OFF: break;
2306                         }
2307                 }
2308                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2311                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2312                 // light source
2313                 mode = SHADERMODE_LIGHTSOURCE;
2314                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2315                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2316                 if (VectorLength2(rtlightdiffuse) > 0)
2317                         permutation |= SHADERPERMUTATION_DIFFUSE;
2318                 if (VectorLength2(rtlightspecular) > 0)
2319                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2320                 if (r_refdef.fogenabled)
2321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322                 if (t->colormapping)
2323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2324                 if (r_shadow_usingshadowmap2d)
2325                 {
2326                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2327                         if(r_shadow_shadowmapvsdct)
2328                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2329
2330                         if (r_shadow_shadowmap2ddepthbuffer)
2331                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2332                 }
2333                 if (t->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2336                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2337                 if (vid.allowalphatocoverage)
2338                         GL_AlphaToCoverage(false);
2339         }
2340         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341         {
2342                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2343                 {
2344                         switch(t->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2355                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2356                 // directional model lighting
2357                 mode = SHADERMODE_LIGHTDIRECTION;
2358                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2359                         permutation |= SHADERPERMUTATION_GLOW;
2360                 if (VectorLength2(t->render_modellight_diffuse))
2361                         permutation |= SHADERPERMUTATION_DIFFUSE;
2362                 if (VectorLength2(t->render_modellight_specular) > 0)
2363                         permutation |= SHADERPERMUTATION_SPECULAR;
2364                 if (r_refdef.fogenabled)
2365                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2366                 if (t->colormapping)
2367                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2368                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369                 {
2370                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2371                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372
2373                         if (r_shadow_shadowmap2ddepthbuffer)
2374                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2375                 }
2376                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2377                         permutation |= SHADERPERMUTATION_REFLECTION;
2378                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2379                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2380                 if (t->reflectmasktexture)
2381                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2382                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2383                 {
2384                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2385                         if (r_shadow_bouncegrid_state.directional)
2386                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2387                 }
2388                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2390                 // when using alphatocoverage, we don't need alphakill
2391                 if (vid.allowalphatocoverage)
2392                 {
2393                         if (r_transparent_alphatocoverage.integer)
2394                         {
2395                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2396                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2397                         }
2398                         else
2399                                 GL_AlphaToCoverage(false);
2400                 }
2401         }
2402         else
2403         {
2404                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2405                 {
2406                         switch(t->offsetmapping)
2407                         {
2408                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2409                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_OFF: break;
2412                         }
2413                 }
2414                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2415                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2416                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2417                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2418                 // lightmapped wall
2419                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420                         permutation |= SHADERPERMUTATION_GLOW;
2421                 if (r_refdef.fogenabled)
2422                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2423                 if (t->colormapping)
2424                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2425                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426                 {
2427                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2428                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429
2430                         if (r_shadow_shadowmap2ddepthbuffer)
2431                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2432                 }
2433                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (t->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (VectorLength2(t->render_lightmap_specular) > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (VectorLength2(t->render_lightmap_specular) > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         if (rsurface.uselightmaptexture)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (VectorLength2(t->render_lightmap_specular) > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegrid_state.directional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2500                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2501         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2502                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2503         switch(vid.renderpath)
2504         {
2505         case RENDERPATH_D3D9:
2506 #ifdef SUPPORTD3D
2507                 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);
2508                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2509                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2510                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2511                 if (mode == SHADERMODE_LIGHTSOURCE)
2512                 {
2513                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2514                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2515                 }
2516                 else
2517                 {
2518                         if (mode == SHADERMODE_LIGHTDIRECTION)
2519                         {
2520                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2521                         }
2522                 }
2523                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2526                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2527                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2536
2537                         // additive passes are only darkened by fog, not tinted
2538                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2539                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2540                 }
2541                 else
2542                 {
2543                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2556                         }
2557                         else
2558                         {
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2562                         }
2563                         // additive passes are only darkened by fog, not tinted
2564                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         else
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2568                         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);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2573                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2576                         if (mode == SHADERMODE_WATER)
2577                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2578                 }
2579                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2580                 {
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2583                 }
2584                 else
2585                 {
2586                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2588                 }
2589                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2590                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2591                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2592                 if (t->pantstexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2596                 if (t->shirttexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2603                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2605                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2606                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2608                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2609                         );
2610                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2611                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2612                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2613                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2614
2615                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2616                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2617                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2618                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2627                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2628                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2629                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2630                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2631                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2632                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2633                 {
2634                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2635                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2636                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638                 else
2639                 {
2640                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2643                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2645                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2646                 {
2647                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2648                         if (rsurface.rtlight)
2649                         {
2650                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2651                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2652                         }
2653                 }
2654 #endif
2655                 break;
2656         case RENDERPATH_D3D10:
2657                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658                 break;
2659         case RENDERPATH_D3D11:
2660                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2661                 break;
2662         case RENDERPATH_GL20:
2663         case RENDERPATH_GLES2:
2664                 if (!vid.useinterleavedarrays)
2665                 {
2666                         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);
2667                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2668                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2675                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2676                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2677                 }
2678                 else
2679                 {
2680                         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);
2681                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2682                 }
2683                 // this has to be after RSurf_PrepareVerticesForBatch
2684                 if (rsurface.batchskeletaltransform3x4buffer)
2685                         permutation |= SHADERPERMUTATION_SKELETAL;
2686                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2687 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2688                 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);
2689 #endif
2690                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2691                 if (mode == SHADERMODE_LIGHTSOURCE)
2692                 {
2693                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2694                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2695                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2696                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2697                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2698                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2699         
2700                         // additive passes are only darkened by fog, not tinted
2701                         if (r_glsl_permutation->loc_FogColor >= 0)
2702                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2703                         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);
2704                 }
2705                 else
2706                 {
2707                         if (mode == SHADERMODE_FLATCOLOR)
2708                         {
2709                                 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]);
2710                         }
2711                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2712                         {
2713                                 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]);
2714                                 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]);
2715                                 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]);
2716                                 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]);
2717                                 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]);
2718                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2719                                 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]);
2720                         }
2721                         else
2722                         {
2723                                 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]);
2724                                 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]);
2725                                 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]);
2726                                 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]);
2727                                 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]);
2728                         }
2729                         // additive passes are only darkened by fog, not tinted
2730                         if (r_glsl_permutation->loc_FogColor >= 0)
2731                         {
2732                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2733                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2734                                 else
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2736                         }
2737                         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);
2738                         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]);
2739                         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]);
2740                         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);
2741                         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);
2742                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2743                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2744                         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);
2745                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2746                 }
2747                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2750                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2751                 {
2752                         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]);
2753                         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]);
2754                 }
2755                 else
2756                 {
2757                         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]);
2758                         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]);
2759                 }
2760
2761                 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]);
2762                 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));
2763                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2764                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2765                 {
2766                         if (t->pantstexture)
2767                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2768                         else
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2770                 }
2771                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2772                 {
2773                         if (t->shirttexture)
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2775                         else
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2777                 }
2778                 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]);
2779                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2780                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2781                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2782                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2783                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2784                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2786                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2787                         );
2788                 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);
2789                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2790                 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]);
2791                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2792                 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);}
2793                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2794
2795                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2796                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2797                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2798                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2799                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2800                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2801                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2802                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2806                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2807                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2808                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2809                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2810                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2811                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2812                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2813                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2814                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2815                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2816                 {
2817                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2818                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2819                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2820                 }
2821                 else
2822                 {
2823                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2824                 }
2825                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2826                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2827                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2828                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2829                 {
2830                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2831                         if (rsurface.rtlight)
2832                         {
2833                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2834                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2835                         }
2836                 }
2837                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2838                 CHECKGLERROR
2839                 break;
2840         case RENDERPATH_GL11:
2841         case RENDERPATH_GL13:
2842         case RENDERPATH_GLES1:
2843                 break;
2844         case RENDERPATH_SOFT:
2845                 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);
2846                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2847                 R_SetupShader_SetPermutationSoft(mode, permutation);
2848                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2849                 if (mode == SHADERMODE_LIGHTSOURCE)
2850                 {
2851                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2857         
2858                         // additive passes are only darkened by fog, not tinted
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2860                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2861                 }
2862                 else
2863                 {
2864                         if (mode == SHADERMODE_FLATCOLOR)
2865                         {
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2867                         }
2868                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2875                         }
2876                         else
2877                         {
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2881                         }
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2884                         // additive passes are only darkened by fog, not tinted
2885                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2887                         else
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2889                         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);
2890                         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]);
2891                         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]);
2892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2896                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2897                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2898                 }
2899                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2900                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2901                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2902                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2903                 {
2904                         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]);
2905                         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]);
2906                 }
2907                 else
2908                 {
2909                         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]);
2910                         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]);
2911                 }
2912
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2915                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2916                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2917                 {
2918                         if (t->pantstexture)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2922                 }
2923                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2924                 {
2925                         if (t->shirttexture)
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2927                         else
2928                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2929                 }
2930                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2934                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2935                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2936                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2939                         );
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2943                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2944
2945                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2946                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2947                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2948                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2957                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2958                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2959                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2960                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2961                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2962                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2963                 {
2964                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2965                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2966                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968                 else
2969                 {
2970                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971                 }
2972 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2974                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2975                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2976                 {
2977                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2978                         if (rsurface.rtlight)
2979                         {
2980                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2981                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2982                         }
2983                 }
2984                 break;
2985         }
2986 }
2987
2988 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2989 {
2990         // select a permutation of the lighting shader appropriate to this
2991         // combination of texture, entity, light source, and fogging, only use the
2992         // minimum features necessary to avoid wasting rendering time in the
2993         // fragment shader on features that are not being used
2994         dpuint64 permutation = 0;
2995         unsigned int mode = 0;
2996         const float *lightcolorbase = rtlight->currentcolor;
2997         float ambientscale = rtlight->ambientscale;
2998         float diffusescale = rtlight->diffusescale;
2999         float specularscale = rtlight->specularscale;
3000         // this is the location of the light in view space
3001         vec3_t viewlightorigin;
3002         // this transforms from view space (camera) to light space (cubemap)
3003         matrix4x4_t viewtolight;
3004         matrix4x4_t lighttoview;
3005         float viewtolight16f[16];
3006         // light source
3007         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3008         if (rtlight->currentcubemap != r_texture_whitecube)
3009                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3010         if (diffusescale > 0)
3011                 permutation |= SHADERPERMUTATION_DIFFUSE;
3012         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3013                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3014         if (r_shadow_usingshadowmap2d)
3015         {
3016                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3017                 if (r_shadow_shadowmapvsdct)
3018                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3019
3020                 if (r_shadow_shadowmap2ddepthbuffer)
3021                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3022         }
3023         if (vid.allowalphatocoverage)
3024                 GL_AlphaToCoverage(false);
3025         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3026         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3027         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3028         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3029         switch(vid.renderpath)
3030         {
3031         case RENDERPATH_D3D9:
3032 #ifdef SUPPORTD3D
3033                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3040                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3041                 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);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3044
3045                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3046                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3047                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3048                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3049                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3050 #endif
3051                 break;
3052         case RENDERPATH_D3D10:
3053                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054                 break;
3055         case RENDERPATH_D3D11:
3056                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057                 break;
3058         case RENDERPATH_GL20:
3059         case RENDERPATH_GLES2:
3060                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3063                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3065                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3066                 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]);
3067                 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]);
3068                 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);
3069                 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]);
3070                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3071
3072                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3073                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3074                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3075                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3076                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3077                 break;
3078         case RENDERPATH_GL11:
3079         case RENDERPATH_GL13:
3080         case RENDERPATH_GLES1:
3081                 break;
3082         case RENDERPATH_SOFT:
3083                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3085                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3089                 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]);
3090                 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]);
3091                 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);
3092                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3093                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3094
3095                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3096                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3097                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3098                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3099                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3100                 break;
3101         }
3102 }
3103
3104 #define SKINFRAME_HASH 1024
3105
3106 typedef struct
3107 {
3108         unsigned int loadsequence; // incremented each level change
3109         memexpandablearray_t array;
3110         skinframe_t *hash[SKINFRAME_HASH];
3111 }
3112 r_skinframe_t;
3113 r_skinframe_t r_skinframe;
3114
3115 void R_SkinFrame_PrepareForPurge(void)
3116 {
3117         r_skinframe.loadsequence++;
3118         // wrap it without hitting zero
3119         if (r_skinframe.loadsequence >= 200)
3120                 r_skinframe.loadsequence = 1;
3121 }
3122
3123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3124 {
3125         if (!skinframe)
3126                 return;
3127         // mark the skinframe as used for the purging code
3128         skinframe->loadsequence = r_skinframe.loadsequence;
3129 }
3130
3131 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3132 {
3133         if (s->merged == s->base)
3134                 s->merged = NULL;
3135         R_PurgeTexture(s->stain); s->stain = NULL;
3136         R_PurgeTexture(s->merged); s->merged = NULL;
3137         R_PurgeTexture(s->base); s->base = NULL;
3138         R_PurgeTexture(s->pants); s->pants = NULL;
3139         R_PurgeTexture(s->shirt); s->shirt = NULL;
3140         R_PurgeTexture(s->nmap); s->nmap = NULL;
3141         R_PurgeTexture(s->gloss); s->gloss = NULL;
3142         R_PurgeTexture(s->glow); s->glow = NULL;
3143         R_PurgeTexture(s->fog); s->fog = NULL;
3144         R_PurgeTexture(s->reflect); s->reflect = NULL;
3145         s->loadsequence = 0;
3146 }
3147
3148 void R_SkinFrame_Purge(void)
3149 {
3150         int i;
3151         skinframe_t *s;
3152         for (i = 0;i < SKINFRAME_HASH;i++)
3153         {
3154                 for (s = r_skinframe.hash[i];s;s = s->next)
3155                 {
3156                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3157                                 R_SkinFrame_PurgeSkinFrame(s);
3158                 }
3159         }
3160 }
3161
3162 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3163         skinframe_t *item;
3164         char basename[MAX_QPATH];
3165
3166         Image_StripImageExtension(name, basename, sizeof(basename));
3167
3168         if( last == NULL ) {
3169                 int hashindex;
3170                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3171                 item = r_skinframe.hash[hashindex];
3172         } else {
3173                 item = last->next;
3174         }
3175
3176         // linearly search through the hash bucket
3177         for( ; item ; item = item->next ) {
3178                 if( !strcmp( item->basename, basename ) ) {
3179                         return item;
3180                 }
3181         }
3182         return NULL;
3183 }
3184
3185 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3186 {
3187         skinframe_t *item;
3188         int hashindex;
3189         char basename[MAX_QPATH];
3190
3191         Image_StripImageExtension(name, basename, sizeof(basename));
3192
3193         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3195                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3196                         break;
3197
3198         if (!item) {
3199                 rtexture_t *dyntexture;
3200                 // check whether its a dynamic texture
3201                 dyntexture = CL_GetDynTexture( basename );
3202                 if (!add && !dyntexture)
3203                         return NULL;
3204                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3205                 memset(item, 0, sizeof(*item));
3206                 strlcpy(item->basename, basename, sizeof(item->basename));
3207                 item->base = dyntexture; // either NULL or dyntexture handle
3208                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3209                 item->comparewidth = comparewidth;
3210                 item->compareheight = compareheight;
3211                 item->comparecrc = comparecrc;
3212                 item->next = r_skinframe.hash[hashindex];
3213                 r_skinframe.hash[hashindex] = item;
3214         }
3215         else if (textureflags & TEXF_FORCE_RELOAD)
3216         {
3217                 rtexture_t *dyntexture;
3218                 // check whether its a dynamic texture
3219                 dyntexture = CL_GetDynTexture( basename );
3220                 if (!add && !dyntexture)
3221                         return NULL;
3222                 R_SkinFrame_PurgeSkinFrame(item);
3223         }
3224         else if( item->base == NULL )
3225         {
3226                 rtexture_t *dyntexture;
3227                 // check whether its a dynamic texture
3228                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3229                 dyntexture = CL_GetDynTexture( basename );
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231         }
3232
3233         R_SkinFrame_MarkUsed(item);
3234         return item;
3235 }
3236
3237 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3238         { \
3239                 unsigned long long avgcolor[5], wsum; \
3240                 int pix, comp, w; \
3241                 avgcolor[0] = 0; \
3242                 avgcolor[1] = 0; \
3243                 avgcolor[2] = 0; \
3244                 avgcolor[3] = 0; \
3245                 avgcolor[4] = 0; \
3246                 wsum = 0; \
3247                 for(pix = 0; pix < cnt; ++pix) \
3248                 { \
3249                         w = 0; \
3250                         for(comp = 0; comp < 3; ++comp) \
3251                                 w += getpixel; \
3252                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3253                         { \
3254                                 ++wsum; \
3255                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                                 w = getpixel; \
3257                                 for(comp = 0; comp < 3; ++comp) \
3258                                         avgcolor[comp] += getpixel * w; \
3259                                 avgcolor[3] += w; \
3260                         } \
3261                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3262                         avgcolor[4] += getpixel; \
3263                 } \
3264                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3265                         avgcolor[3] = 1; \
3266                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3267                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3270         }
3271
3272 extern cvar_t gl_picmip;
3273 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3274 {
3275         int j;
3276         unsigned char *pixels;
3277         unsigned char *bumppixels;
3278         unsigned char *basepixels = NULL;
3279         int basepixels_width = 0;
3280         int basepixels_height = 0;
3281         skinframe_t *skinframe;
3282         rtexture_t *ddsbase = NULL;
3283         qboolean ddshasalpha = false;
3284         float ddsavgcolor[4];
3285         char basename[MAX_QPATH];
3286         int miplevel = R_PicmipForFlags(textureflags);
3287         int savemiplevel = miplevel;
3288         int mymiplevel;
3289         char vabuf[1024];
3290
3291         if (cls.state == ca_dedicated)
3292                 return NULL;
3293
3294         // return an existing skinframe if already loaded
3295         // if loading of the first image fails, don't make a new skinframe as it
3296         // would cause all future lookups of this to be missing
3297         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3298         if (skinframe && skinframe->base)
3299                 return skinframe;
3300
3301         Image_StripImageExtension(name, basename, sizeof(basename));
3302
3303         // check for DDS texture file first
3304         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3305         {
3306                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3307                 if (basepixels == NULL)
3308                         return NULL;
3309         }
3310
3311         // FIXME handle miplevel
3312
3313         if (developer_loading.integer)
3314                 Con_Printf("loading skin \"%s\"\n", name);
3315
3316         // we've got some pixels to store, so really allocate this new texture now
3317         if (!skinframe)
3318                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3319         textureflags &= ~TEXF_FORCE_RELOAD;
3320         skinframe->stain = NULL;
3321         skinframe->merged = NULL;
3322         skinframe->base = NULL;
3323         skinframe->pants = NULL;
3324         skinframe->shirt = NULL;
3325         skinframe->nmap = NULL;
3326         skinframe->gloss = NULL;
3327         skinframe->glow = NULL;
3328         skinframe->fog = NULL;
3329         skinframe->reflect = NULL;
3330         skinframe->hasalpha = false;
3331         // we could store the q2animname here too
3332
3333         if (ddsbase)
3334         {
3335                 skinframe->base = ddsbase;
3336                 skinframe->hasalpha = ddshasalpha;
3337                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3338                 if (r_loadfog && skinframe->hasalpha)
3339                         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);
3340                 //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]);
3341         }
3342         else
3343         {
3344                 basepixels_width = image_width;
3345                 basepixels_height = image_height;
3346                 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);
3347                 if (textureflags & TEXF_ALPHA)
3348                 {
3349                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3350                         {
3351                                 if (basepixels[j] < 255)
3352                                 {
3353                                         skinframe->hasalpha = true;
3354                                         break;
3355                                 }
3356                         }
3357                         if (r_loadfog && skinframe->hasalpha)
3358                         {
3359                                 // has transparent pixels
3360                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3361                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3362                                 {
3363                                         pixels[j+0] = 255;
3364                                         pixels[j+1] = 255;
3365                                         pixels[j+2] = 255;
3366                                         pixels[j+3] = basepixels[j+3];
3367                                 }
3368                                 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);
3369                                 Mem_Free(pixels);
3370                         }
3371                 }
3372                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3373 #ifndef USE_GLES2
3374                 //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]);
3375                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3376                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3377                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3378                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3379 #endif
3380         }
3381
3382         if (r_loaddds)
3383         {
3384                 mymiplevel = savemiplevel;
3385                 if (r_loadnormalmap)
3386                         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);
3387                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3388                 if (r_loadgloss)
3389                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3390                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3391                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3392                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3393         }
3394
3395         // _norm is the name used by tenebrae and has been adopted as standard
3396         if (r_loadnormalmap && skinframe->nmap == NULL)
3397         {
3398                 mymiplevel = savemiplevel;
3399                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         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);
3402                         Mem_Free(pixels);
3403                         pixels = NULL;
3404                 }
3405                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3406                 {
3407                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3408                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3409                         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);
3410                         Mem_Free(pixels);
3411                         Mem_Free(bumppixels);
3412                 }
3413                 else if (r_shadow_bumpscale_basetexture.value > 0)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3417                         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);
3418                         Mem_Free(pixels);
3419                 }
3420 #ifndef USE_GLES2
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3422                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3423 #endif
3424         }
3425
3426         // _luma is supported only for tenebrae compatibility
3427         // _glow is the preferred name
3428         mymiplevel = savemiplevel;
3429         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))))
3430         {
3431                 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);
3432 #ifndef USE_GLES2
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3434                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3435 #endif
3436                 Mem_Free(pixels);pixels = NULL;
3437         }
3438
3439         mymiplevel = savemiplevel;
3440         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3441         {
3442                 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);
3443 #ifndef USE_GLES2
3444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3445                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 #endif
3447                 Mem_Free(pixels);
3448                 pixels = NULL;
3449         }
3450
3451         mymiplevel = savemiplevel;
3452         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3453         {
3454                 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);
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3457                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3458 #endif
3459                 Mem_Free(pixels);
3460                 pixels = NULL;
3461         }
3462
3463         mymiplevel = savemiplevel;
3464         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3465         {
3466                 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);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3469                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3470 #endif
3471                 Mem_Free(pixels);
3472                 pixels = NULL;
3473         }
3474
3475         mymiplevel = savemiplevel;
3476         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3477         {
3478                 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);
3479 #ifndef USE_GLES2
3480                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3481                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3482 #endif
3483                 Mem_Free(pixels);
3484                 pixels = NULL;
3485         }
3486
3487         if (basepixels)
3488                 Mem_Free(basepixels);
3489
3490         return skinframe;
3491 }
3492
3493 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3494 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3495 {
3496         int i;
3497         skinframe_t *skinframe;
3498         char vabuf[1024];
3499
3500         if (cls.state == ca_dedicated)
3501                 return NULL;
3502
3503         // if already loaded just return it, otherwise make a new skinframe
3504         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3505         if (skinframe->base)
3506                 return skinframe;
3507         textureflags &= ~TEXF_FORCE_RELOAD;
3508
3509         skinframe->stain = NULL;
3510         skinframe->merged = NULL;
3511         skinframe->base = NULL;
3512         skinframe->pants = NULL;
3513         skinframe->shirt = NULL;
3514         skinframe->nmap = NULL;
3515         skinframe->gloss = NULL;
3516         skinframe->glow = NULL;
3517         skinframe->fog = NULL;
3518         skinframe->reflect = NULL;
3519         skinframe->hasalpha = false;
3520
3521         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3522         if (!skindata)
3523                 return NULL;
3524
3525         if (developer_loading.integer)
3526                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3527
3528         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3529         {
3530                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3531                 unsigned char *b = a + width * height * 4;
3532                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3533                 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);
3534                 Mem_Free(a);
3535         }
3536         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3537         if (textureflags & TEXF_ALPHA)
3538         {
3539                 for (i = 3;i < width * height * 4;i += 4)
3540                 {
3541                         if (skindata[i] < 255)
3542                         {
3543                                 skinframe->hasalpha = true;
3544                                 break;
3545                         }
3546                 }
3547                 if (r_loadfog && skinframe->hasalpha)
3548                 {
3549                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3550                         memcpy(fogpixels, skindata, width * height * 4);
3551                         for (i = 0;i < width * height * 4;i += 4)
3552                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3553                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3554                         Mem_Free(fogpixels);
3555                 }
3556         }
3557
3558         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3559         //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]);
3560
3561         return skinframe;
3562 }
3563
3564 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3565 {
3566         int i;
3567         int featuresmask;
3568         skinframe_t *skinframe;
3569
3570         if (cls.state == ca_dedicated)
3571                 return NULL;
3572
3573         // if already loaded just return it, otherwise make a new skinframe
3574         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3575         if (skinframe->base)
3576                 return skinframe;
3577         //textureflags &= ~TEXF_FORCE_RELOAD;
3578
3579         skinframe->stain = NULL;
3580         skinframe->merged = NULL;
3581         skinframe->base = NULL;
3582         skinframe->pants = NULL;
3583         skinframe->shirt = NULL;
3584         skinframe->nmap = NULL;
3585         skinframe->gloss = NULL;
3586         skinframe->glow = NULL;
3587         skinframe->fog = NULL;
3588         skinframe->reflect = NULL;
3589         skinframe->hasalpha = false;
3590
3591         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3592         if (!skindata)
3593                 return NULL;
3594
3595         if (developer_loading.integer)
3596                 Con_Printf("loading quake skin \"%s\"\n", name);
3597
3598         // 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)
3599         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3600         memcpy(skinframe->qpixels, skindata, width*height);
3601         skinframe->qwidth = width;
3602         skinframe->qheight = height;
3603
3604         featuresmask = 0;
3605         for (i = 0;i < width * height;i++)
3606                 featuresmask |= palette_featureflags[skindata[i]];
3607
3608         skinframe->hasalpha = false;
3609         // fence textures
3610         if (name[0] == '{')
3611                 skinframe->hasalpha = true;
3612         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3613         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3614         skinframe->qgeneratemerged = true;
3615         skinframe->qgeneratebase = skinframe->qhascolormapping;
3616         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3617
3618         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3619         //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]);
3620
3621         return skinframe;
3622 }
3623
3624 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3625 {
3626         int width;
3627         int height;
3628         unsigned char *skindata;
3629         char vabuf[1024];
3630
3631         if (!skinframe->qpixels)
3632                 return;
3633
3634         if (!skinframe->qhascolormapping)
3635                 colormapped = false;
3636
3637         if (colormapped)
3638         {
3639                 if (!skinframe->qgeneratebase)
3640                         return;
3641         }
3642         else
3643         {
3644                 if (!skinframe->qgeneratemerged)
3645                         return;
3646         }
3647
3648         width = skinframe->qwidth;
3649         height = skinframe->qheight;
3650         skindata = skinframe->qpixels;
3651
3652         if (skinframe->qgeneratenmap)
3653         {
3654                 unsigned char *a, *b;
3655                 skinframe->qgeneratenmap = false;
3656                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3657                 b = a + width * height * 4;
3658                 // use either a custom palette or the quake palette
3659                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3660                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3661                 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);
3662                 Mem_Free(a);
3663         }
3664
3665         if (skinframe->qgenerateglow)
3666         {
3667                 skinframe->qgenerateglow = false;
3668                 if (skinframe->hasalpha) // fence textures
3669                         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
3670                 else
3671                         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
3672         }
3673
3674         if (colormapped)
3675         {
3676                 skinframe->qgeneratebase = false;
3677                 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);
3678                 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);
3679                 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);
3680         }
3681         else
3682         {
3683                 skinframe->qgeneratemerged = false;
3684                 if (skinframe->hasalpha) // fence textures
3685                         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);
3686                 else
3687                         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);
3688         }
3689
3690         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3691         {
3692                 Mem_Free(skinframe->qpixels);
3693                 skinframe->qpixels = NULL;
3694         }
3695 }
3696
3697 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)
3698 {
3699         int i;
3700         skinframe_t *skinframe;
3701         char vabuf[1024];
3702
3703         if (cls.state == ca_dedicated)
3704                 return NULL;
3705
3706         // if already loaded just return it, otherwise make a new skinframe
3707         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3708         if (skinframe->base)
3709                 return skinframe;
3710         textureflags &= ~TEXF_FORCE_RELOAD;
3711
3712         skinframe->stain = NULL;
3713         skinframe->merged = NULL;
3714         skinframe->base = NULL;
3715         skinframe->pants = NULL;
3716         skinframe->shirt = NULL;
3717         skinframe->nmap = NULL;
3718         skinframe->gloss = NULL;
3719         skinframe->glow = NULL;
3720         skinframe->fog = NULL;
3721         skinframe->reflect = NULL;
3722         skinframe->hasalpha = false;
3723
3724         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3725         if (!skindata)
3726                 return NULL;
3727
3728         if (developer_loading.integer)
3729                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3730
3731         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3732         if (textureflags & TEXF_ALPHA)
3733         {
3734                 for (i = 0;i < width * height;i++)
3735                 {
3736                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3737                         {
3738                                 skinframe->hasalpha = true;
3739                                 break;
3740                         }
3741                 }
3742                 if (r_loadfog && skinframe->hasalpha)
3743                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3744         }
3745
3746         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3747         //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]);
3748
3749         return skinframe;
3750 }
3751
3752 skinframe_t *R_SkinFrame_LoadMissing(void)
3753 {
3754         skinframe_t *skinframe;
3755
3756         if (cls.state == ca_dedicated)
3757                 return NULL;
3758
3759         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3760         skinframe->stain = NULL;
3761         skinframe->merged = NULL;
3762         skinframe->base = NULL;
3763         skinframe->pants = NULL;
3764         skinframe->shirt = NULL;
3765         skinframe->nmap = NULL;
3766         skinframe->gloss = NULL;
3767         skinframe->glow = NULL;
3768         skinframe->fog = NULL;
3769         skinframe->reflect = NULL;
3770         skinframe->hasalpha = false;
3771
3772         skinframe->avgcolor[0] = rand() / RAND_MAX;
3773         skinframe->avgcolor[1] = rand() / RAND_MAX;
3774         skinframe->avgcolor[2] = rand() / RAND_MAX;
3775         skinframe->avgcolor[3] = 1;
3776
3777         return skinframe;
3778 }
3779
3780 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3781 typedef struct suffixinfo_s
3782 {
3783         const char *suffix;
3784         qboolean flipx, flipy, flipdiagonal;
3785 }
3786 suffixinfo_t;
3787 static suffixinfo_t suffix[3][6] =
3788 {
3789         {
3790                 {"px",   false, false, false},
3791                 {"nx",   false, false, false},
3792                 {"py",   false, false, false},
3793                 {"ny",   false, false, false},
3794                 {"pz",   false, false, false},
3795                 {"nz",   false, false, false}
3796         },
3797         {
3798                 {"posx", false, false, false},
3799                 {"negx", false, false, false},
3800                 {"posy", false, false, false},
3801                 {"negy", false, false, false},
3802                 {"posz", false, false, false},
3803                 {"negz", false, false, false}
3804         },
3805         {
3806                 {"rt",    true, false,  true},
3807                 {"lf",   false,  true,  true},
3808                 {"ft",    true,  true, false},
3809                 {"bk",   false, false, false},
3810                 {"up",    true, false,  true},
3811                 {"dn",    true, false,  true}
3812         }
3813 };
3814
3815 static int componentorder[4] = {0, 1, 2, 3};
3816
3817 static rtexture_t *R_LoadCubemap(const char *basename)
3818 {
3819         int i, j, cubemapsize;
3820         unsigned char *cubemappixels, *image_buffer;
3821         rtexture_t *cubemaptexture;
3822         char name[256];
3823         // must start 0 so the first loadimagepixels has no requested width/height
3824         cubemapsize = 0;
3825         cubemappixels = NULL;
3826         cubemaptexture = NULL;
3827         // keep trying different suffix groups (posx, px, rt) until one loads
3828         for (j = 0;j < 3 && !cubemappixels;j++)
3829         {
3830                 // load the 6 images in the suffix group
3831                 for (i = 0;i < 6;i++)
3832                 {
3833                         // generate an image name based on the base and and suffix
3834                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3835                         // load it
3836                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3837                         {
3838                                 // an image loaded, make sure width and height are equal
3839                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3840                                 {
3841                                         // if this is the first image to load successfully, allocate the cubemap memory
3842                                         if (!cubemappixels && image_width >= 1)
3843                                         {
3844                                                 cubemapsize = image_width;
3845                                                 // note this clears to black, so unavailable sides are black
3846                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3847                                         }
3848                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3849                                         if (cubemappixels)
3850                                                 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);
3851                                 }
3852                                 else
3853                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3854                                 // free the image
3855                                 Mem_Free(image_buffer);
3856                         }
3857                 }
3858         }
3859         // if a cubemap loaded, upload it
3860         if (cubemappixels)
3861         {
3862                 if (developer_loading.integer)
3863                         Con_Printf("loading cubemap \"%s\"\n", basename);
3864
3865                 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);
3866                 Mem_Free(cubemappixels);
3867         }
3868         else
3869         {
3870                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3871                 if (developer_loading.integer)
3872                 {
3873                         Con_Printf("(tried tried images ");
3874                         for (j = 0;j < 3;j++)
3875                                 for (i = 0;i < 6;i++)
3876                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3877                         Con_Print(" and was unable to find any of them).\n");
3878                 }
3879         }
3880         return cubemaptexture;
3881 }
3882
3883 rtexture_t *R_GetCubemap(const char *basename)
3884 {
3885         int i;
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887                 if (r_texture_cubemaps[i] != NULL)
3888                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3889                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3890         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3891                 return r_texture_whitecube;
3892         r_texture_numcubemaps++;
3893         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3894         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3895         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3896         return r_texture_cubemaps[i]->texture;
3897 }
3898
3899 static void R_Main_FreeViewCache(void)
3900 {
3901         if (r_refdef.viewcache.entityvisible)
3902                 Mem_Free(r_refdef.viewcache.entityvisible);
3903         if (r_refdef.viewcache.world_pvsbits)
3904                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3905         if (r_refdef.viewcache.world_leafvisible)
3906                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3907         if (r_refdef.viewcache.world_surfacevisible)
3908                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3909         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3910 }
3911
3912 static void R_Main_ResizeViewCache(void)
3913 {
3914         int numentities = r_refdef.scene.numentities;
3915         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3916         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3917         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3918         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3919         if (r_refdef.viewcache.maxentities < numentities)
3920         {
3921                 r_refdef.viewcache.maxentities = numentities;
3922                 if (r_refdef.viewcache.entityvisible)
3923                         Mem_Free(r_refdef.viewcache.entityvisible);
3924                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3925         }
3926         if (r_refdef.viewcache.world_numclusters != numclusters)
3927         {
3928                 r_refdef.viewcache.world_numclusters = numclusters;
3929                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3930                 if (r_refdef.viewcache.world_pvsbits)
3931                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3932                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3933         }
3934         if (r_refdef.viewcache.world_numleafs != numleafs)
3935         {
3936                 r_refdef.viewcache.world_numleafs = numleafs;
3937                 if (r_refdef.viewcache.world_leafvisible)
3938                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3939                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3940         }
3941         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3942         {
3943                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3944                 if (r_refdef.viewcache.world_surfacevisible)
3945                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3946                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3947         }
3948 }
3949
3950 extern rtexture_t *loadingscreentexture;
3951 static void gl_main_start(void)
3952 {
3953         loadingscreentexture = NULL;
3954         r_texture_blanknormalmap = NULL;
3955         r_texture_white = NULL;
3956         r_texture_grey128 = NULL;
3957         r_texture_black = NULL;
3958         r_texture_whitecube = NULL;
3959         r_texture_normalizationcube = NULL;
3960         r_texture_fogattenuation = NULL;
3961         r_texture_fogheighttexture = NULL;
3962         r_texture_gammaramps = NULL;
3963         r_texture_numcubemaps = 0;
3964         r_uniformbufferalignment = 32;
3965
3966         r_loaddds = r_texture_dds_load.integer != 0;
3967         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3968
3969         switch(vid.renderpath)
3970         {
3971         case RENDERPATH_GL20:
3972         case RENDERPATH_D3D9:
3973         case RENDERPATH_D3D10:
3974         case RENDERPATH_D3D11:
3975         case RENDERPATH_SOFT:
3976         case RENDERPATH_GLES2:
3977                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3978                 Cvar_SetValueQuick(&gl_combine, 1);
3979                 Cvar_SetValueQuick(&r_glsl, 1);
3980                 r_loadnormalmap = true;
3981                 r_loadgloss = true;
3982                 r_loadfog = false;
3983 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3984                 if (vid.support.arb_uniform_buffer_object)
3985                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3986 #endif
3987                         break;
3988         case RENDERPATH_GL13:
3989         case RENDERPATH_GLES1:
3990                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991                 Cvar_SetValueQuick(&gl_combine, 1);
3992                 Cvar_SetValueQuick(&r_glsl, 0);
3993                 r_loadnormalmap = false;
3994                 r_loadgloss = false;
3995                 r_loadfog = true;
3996                 break;
3997         case RENDERPATH_GL11:
3998                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3999                 Cvar_SetValueQuick(&gl_combine, 0);
4000                 Cvar_SetValueQuick(&r_glsl, 0);
4001                 r_loadnormalmap = false;
4002                 r_loadgloss = false;
4003                 r_loadfog = true;
4004                 break;
4005         }
4006
4007         R_AnimCache_Free();
4008         R_FrameData_Reset();
4009         R_BufferData_Reset();
4010
4011         r_numqueries = 0;
4012         r_maxqueries = 0;
4013         memset(r_queries, 0, sizeof(r_queries));
4014
4015         r_qwskincache = NULL;
4016         r_qwskincache_size = 0;
4017
4018         // due to caching of texture_t references, the collision cache must be reset
4019         Collision_Cache_Reset(true);
4020
4021         // set up r_skinframe loading system for textures
4022         memset(&r_skinframe, 0, sizeof(r_skinframe));
4023         r_skinframe.loadsequence = 1;
4024         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4025
4026         r_main_texturepool = R_AllocTexturePool();
4027         R_BuildBlankTextures();
4028         R_BuildNoTexture();
4029         if (vid.support.arb_texture_cube_map)
4030         {
4031                 R_BuildWhiteCube();
4032                 R_BuildNormalizationCube();
4033         }
4034         r_texture_fogattenuation = NULL;
4035         r_texture_fogheighttexture = NULL;
4036         r_texture_gammaramps = NULL;
4037         //r_texture_fogintensity = NULL;
4038         memset(&r_fb, 0, sizeof(r_fb));
4039         r_glsl_permutation = NULL;
4040         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4041         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4042 #ifdef SUPPORTD3D
4043         r_hlsl_permutation = NULL;
4044         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4045         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4046 #endif
4047         memset(&r_svbsp, 0, sizeof (r_svbsp));
4048
4049         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4050         r_texture_numcubemaps = 0;
4051
4052         r_refdef.fogmasktable_density = 0;
4053
4054 #ifdef __ANDROID__
4055         // For Steelstorm Android
4056         // FIXME CACHE the program and reload
4057         // FIXME see possible combinations for SS:BR android
4058         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4059         R_SetupShader_SetPermutationGLSL(0, 12);
4060         R_SetupShader_SetPermutationGLSL(0, 13);
4061         R_SetupShader_SetPermutationGLSL(0, 8388621);
4062         R_SetupShader_SetPermutationGLSL(3, 0);
4063         R_SetupShader_SetPermutationGLSL(3, 2048);
4064         R_SetupShader_SetPermutationGLSL(5, 0);
4065         R_SetupShader_SetPermutationGLSL(5, 2);
4066         R_SetupShader_SetPermutationGLSL(5, 2048);
4067         R_SetupShader_SetPermutationGLSL(5, 8388608);
4068         R_SetupShader_SetPermutationGLSL(11, 1);
4069         R_SetupShader_SetPermutationGLSL(11, 2049);
4070         R_SetupShader_SetPermutationGLSL(11, 8193);
4071         R_SetupShader_SetPermutationGLSL(11, 10241);
4072         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4073 #endif
4074 }
4075
4076 static void gl_main_shutdown(void)
4077 {
4078         R_AnimCache_Free();
4079         R_FrameData_Reset();
4080         R_BufferData_Reset();
4081
4082         R_Main_FreeViewCache();
4083
4084         switch(vid.renderpath)
4085         {
4086         case RENDERPATH_GL11:
4087         case RENDERPATH_GL13:
4088         case RENDERPATH_GL20:
4089         case RENDERPATH_GLES1:
4090         case RENDERPATH_GLES2:
4091 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4092                 if (r_maxqueries)
4093                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4094 #endif
4095                 break;
4096         case RENDERPATH_D3D9:
4097                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4098                 break;
4099         case RENDERPATH_D3D10:
4100                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4101                 break;
4102         case RENDERPATH_D3D11:
4103                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_SOFT:
4106                 break;
4107         }
4108
4109         r_numqueries = 0;
4110         r_maxqueries = 0;
4111         memset(r_queries, 0, sizeof(r_queries));
4112
4113         r_qwskincache = NULL;
4114         r_qwskincache_size = 0;
4115
4116         // clear out the r_skinframe state
4117         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4118         memset(&r_skinframe, 0, sizeof(r_skinframe));
4119
4120         if (r_svbsp.nodes)
4121                 Mem_Free(r_svbsp.nodes);
4122         memset(&r_svbsp, 0, sizeof (r_svbsp));
4123         R_FreeTexturePool(&r_main_texturepool);
4124         loadingscreentexture = NULL;
4125         r_texture_blanknormalmap = NULL;
4126         r_texture_white = NULL;
4127         r_texture_grey128 = NULL;
4128         r_texture_black = NULL;
4129         r_texture_whitecube = NULL;
4130         r_texture_normalizationcube = NULL;
4131         r_texture_fogattenuation = NULL;
4132         r_texture_fogheighttexture = NULL;
4133         r_texture_gammaramps = NULL;
4134         r_texture_numcubemaps = 0;
4135         //r_texture_fogintensity = NULL;
4136         memset(&r_fb, 0, sizeof(r_fb));
4137         R_GLSL_Restart_f();
4138
4139         r_glsl_permutation = NULL;
4140         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4141         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4142 #ifdef SUPPORTD3D
4143         r_hlsl_permutation = NULL;
4144         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4145         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4146 #endif
4147 }
4148
4149 static void gl_main_newmap(void)
4150 {
4151         // FIXME: move this code to client
4152         char *entities, entname[MAX_QPATH];
4153         if (r_qwskincache)
4154                 Mem_Free(r_qwskincache);
4155         r_qwskincache = NULL;
4156         r_qwskincache_size = 0;
4157         if (cl.worldmodel)
4158         {
4159                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4160                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4161                 {
4162                         CL_ParseEntityLump(entities);
4163                         Mem_Free(entities);
4164                         return;
4165                 }
4166                 if (cl.worldmodel->brush.entities)
4167                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4168         }
4169         R_Main_FreeViewCache();
4170
4171         R_FrameData_Reset();
4172         R_BufferData_Reset();
4173 }
4174
4175 void GL_Main_Init(void)
4176 {
4177         int i;
4178         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4179         R_InitShaderModeInfo();
4180
4181         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4182         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4183         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4184         if (gamemode == GAME_NEHAHRA)
4185         {
4186                 Cvar_RegisterVariable (&gl_fogenable);
4187                 Cvar_RegisterVariable (&gl_fogdensity);
4188                 Cvar_RegisterVariable (&gl_fogred);
4189                 Cvar_RegisterVariable (&gl_foggreen);
4190                 Cvar_RegisterVariable (&gl_fogblue);
4191                 Cvar_RegisterVariable (&gl_fogstart);
4192                 Cvar_RegisterVariable (&gl_fogend);
4193                 Cvar_RegisterVariable (&gl_skyclip);
4194         }
4195         Cvar_RegisterVariable(&r_motionblur);
4196         Cvar_RegisterVariable(&r_damageblur);
4197         Cvar_RegisterVariable(&r_motionblur_averaging);
4198         Cvar_RegisterVariable(&r_motionblur_randomize);
4199         Cvar_RegisterVariable(&r_motionblur_minblur);
4200         Cvar_RegisterVariable(&r_motionblur_maxblur);
4201         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4202         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4203         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4204         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4205         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4206         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4207         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4208         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4209         Cvar_RegisterVariable(&r_equalize_entities_by);
4210         Cvar_RegisterVariable(&r_equalize_entities_to);
4211         Cvar_RegisterVariable(&r_depthfirst);
4212         Cvar_RegisterVariable(&r_useinfinitefarclip);
4213         Cvar_RegisterVariable(&r_farclip_base);
4214         Cvar_RegisterVariable(&r_farclip_world);
4215         Cvar_RegisterVariable(&r_nearclip);
4216         Cvar_RegisterVariable(&r_deformvertexes);
4217         Cvar_RegisterVariable(&r_transparent);
4218         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4219         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4220         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4221         Cvar_RegisterVariable(&r_showoverdraw);
4222         Cvar_RegisterVariable(&r_showbboxes);
4223         Cvar_RegisterVariable(&r_showbboxes_client);
4224         Cvar_RegisterVariable(&r_showsurfaces);
4225         Cvar_RegisterVariable(&r_showtris);
4226         Cvar_RegisterVariable(&r_shownormals);
4227         Cvar_RegisterVariable(&r_showlighting);
4228         Cvar_RegisterVariable(&r_showshadowvolumes);
4229         Cvar_RegisterVariable(&r_showcollisionbrushes);
4230         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4231         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4232         Cvar_RegisterVariable(&r_showdisabledepthtest);
4233         Cvar_RegisterVariable(&r_drawportals);
4234         Cvar_RegisterVariable(&r_drawentities);
4235         Cvar_RegisterVariable(&r_draw2d);
4236         Cvar_RegisterVariable(&r_drawworld);
4237         Cvar_RegisterVariable(&r_cullentities_trace);
4238         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4239         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4240         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4241         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4242         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4243         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4244         Cvar_RegisterVariable(&r_sortentities);
4245         Cvar_RegisterVariable(&r_drawviewmodel);
4246         Cvar_RegisterVariable(&r_drawexteriormodel);
4247         Cvar_RegisterVariable(&r_speeds);
4248         Cvar_RegisterVariable(&r_fullbrights);
4249         Cvar_RegisterVariable(&r_wateralpha);
4250         Cvar_RegisterVariable(&r_dynamic);
4251         Cvar_RegisterVariable(&r_fakelight);
4252         Cvar_RegisterVariable(&r_fakelight_intensity);
4253         Cvar_RegisterVariable(&r_fullbright_directed);
4254         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4255         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4256         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4257         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4258         Cvar_RegisterVariable(&r_fullbright);
4259         Cvar_RegisterVariable(&r_shadows);
4260         Cvar_RegisterVariable(&r_shadows_darken);
4261         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4262         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4263         Cvar_RegisterVariable(&r_shadows_throwdistance);
4264         Cvar_RegisterVariable(&r_shadows_throwdirection);
4265         Cvar_RegisterVariable(&r_shadows_focus);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4267         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4268         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4270         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4272         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4273         Cvar_RegisterVariable(&r_fog_exp2);
4274         Cvar_RegisterVariable(&r_fog_clear);
4275         Cvar_RegisterVariable(&r_drawfog);
4276         Cvar_RegisterVariable(&r_transparentdepthmasking);
4277         Cvar_RegisterVariable(&r_transparent_sortmindist);
4278         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4279         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4280         Cvar_RegisterVariable(&r_texture_dds_load);
4281         Cvar_RegisterVariable(&r_texture_dds_save);
4282         Cvar_RegisterVariable(&r_textureunits);
4283         Cvar_RegisterVariable(&gl_combine);
4284         Cvar_RegisterVariable(&r_usedepthtextures);
4285         Cvar_RegisterVariable(&r_viewfbo);
4286         Cvar_RegisterVariable(&r_viewscale);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4293         Cvar_RegisterVariable(&r_glsl);
4294         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4302         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4303         Cvar_RegisterVariable(&r_glsl_postprocess);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4312         Cvar_RegisterVariable(&r_celshading);
4313         Cvar_RegisterVariable(&r_celoutlines);
4314
4315         Cvar_RegisterVariable(&r_water);
4316         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4317         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4318         Cvar_RegisterVariable(&r_water_clippingplanebias);
4319         Cvar_RegisterVariable(&r_water_refractdistort);
4320         Cvar_RegisterVariable(&r_water_reflectdistort);
4321         Cvar_RegisterVariable(&r_water_scissormode);
4322         Cvar_RegisterVariable(&r_water_lowquality);
4323         Cvar_RegisterVariable(&r_water_hideplayer);
4324         Cvar_RegisterVariable(&r_water_fbo);
4325
4326         Cvar_RegisterVariable(&r_lerpsprites);
4327         Cvar_RegisterVariable(&r_lerpmodels);
4328         Cvar_RegisterVariable(&r_lerplightstyles);
4329         Cvar_RegisterVariable(&r_waterscroll);
4330         Cvar_RegisterVariable(&r_bloom);
4331         Cvar_RegisterVariable(&r_bloom_colorscale);
4332         Cvar_RegisterVariable(&r_bloom_brighten);
4333         Cvar_RegisterVariable(&r_bloom_blur);
4334         Cvar_RegisterVariable(&r_bloom_resolution);
4335         Cvar_RegisterVariable(&r_bloom_colorexponent);
4336         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4337         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4338         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4339         Cvar_RegisterVariable(&r_hdr_glowintensity);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4346         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4347         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4348         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4349         Cvar_RegisterVariable(&developer_texturelogging);
4350         Cvar_RegisterVariable(&gl_lightmaps);
4351         Cvar_RegisterVariable(&r_test);
4352         Cvar_RegisterVariable(&r_batch_multidraw);
4353         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4354         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4355         Cvar_RegisterVariable(&r_glsl_skeletal);
4356         Cvar_RegisterVariable(&r_glsl_saturation);
4357         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4358         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4359         Cvar_RegisterVariable(&r_framedatasize);
4360         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4361                 Cvar_RegisterVariable(&r_buffermegs[i]);
4362         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4363         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4364                 Cvar_SetValue("r_fullbrights", 0);
4365 #ifdef DP_MOBILETOUCH
4366         // GLES devices have terrible depth precision in general, so...
4367         Cvar_SetValueQuick(&r_nearclip, 4);
4368         Cvar_SetValueQuick(&r_farclip_base, 4096);
4369         Cvar_SetValueQuick(&r_farclip_world, 0);
4370         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4371 #endif
4372         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4373 }
4374
4375 void Render_Init(void)
4376 {
4377         gl_backend_init();
4378         R_Textures_Init();
4379         GL_Main_Init();
4380         Font_Init();
4381         GL_Draw_Init();
4382         R_Shadow_Init();
4383         R_Sky_Init();
4384         GL_Surf_Init();
4385         Sbar_Init();
4386         R_Particles_Init();
4387         R_Explosion_Init();
4388         R_LightningBeams_Init();
4389         Mod_RenderInit();
4390 }
4391
4392 /*
4393 ===============
4394 GL_Init
4395 ===============
4396 */
4397 #ifndef USE_GLES2
4398 extern char *ENGINE_EXTENSIONS;
4399 void GL_Init (void)
4400 {
4401         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4402         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4403         gl_version = (const char *)qglGetString(GL_VERSION);
4404         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4405
4406         if (!gl_extensions)
4407                 gl_extensions = "";
4408         if (!gl_platformextensions)
4409                 gl_platformextensions = "";
4410
4411         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4412         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4413         Con_Printf("GL_VERSION: %s\n", gl_version);
4414         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4415         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4416
4417         VID_CheckExtensions();
4418
4419         // LordHavoc: report supported extensions
4420 #ifdef CONFIG_MENU
4421         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4422 #else
4423         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4424 #endif
4425
4426         // clear to black (loading plaque will be seen over this)
4427         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4428 }
4429 #endif
4430
4431 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4432 {
4433         int i;
4434         mplane_t *p;
4435         if (r_trippy.integer)
4436                 return false;
4437         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4438         {
4439                 p = r_refdef.view.frustum + i;
4440                 switch(p->signbits)
4441                 {
4442                 default:
4443                 case 0:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 1:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 2:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 3:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 4:
4460                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 5:
4464                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 6:
4468                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 7:
4472                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 }
4476         }
4477         return false;
4478 }
4479
4480 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4481 {
4482         int i;
4483         const mplane_t *p;
4484         if (r_trippy.integer)
4485                 return false;
4486         for (i = 0;i < numplanes;i++)
4487         {
4488                 p = planes + i;
4489                 switch(p->signbits)
4490                 {
4491                 default:
4492                 case 0:
4493                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 case 1:
4497                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4498                                 return true;
4499                         break;
4500                 case 2:
4501                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4502                                 return true;
4503                         break;
4504                 case 3:
4505                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4506                                 return true;
4507                         break;
4508                 case 4:
4509                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4510                                 return true;
4511                         break;
4512                 case 5:
4513                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4514                                 return true;
4515                         break;
4516                 case 6:
4517                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4518                                 return true;
4519                         break;
4520                 case 7:
4521                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4522                                 return true;
4523                         break;
4524                 }
4525         }
4526         return false;
4527 }
4528
4529 //==================================================================================
4530
4531 // LordHavoc: this stores temporary data used within the same frame
4532
4533 typedef struct r_framedata_mem_s
4534 {
4535         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4536         size_t size; // how much usable space
4537         size_t current; // how much space in use
4538         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4539         size_t wantedsize; // how much space was allocated
4540         unsigned char *data; // start of real data (16byte aligned)
4541 }
4542 r_framedata_mem_t;
4543
4544 static r_framedata_mem_t *r_framedata_mem;
4545
4546 void R_FrameData_Reset(void)
4547 {
4548         while (r_framedata_mem)
4549         {
4550                 r_framedata_mem_t *next = r_framedata_mem->purge;
4551                 Mem_Free(r_framedata_mem);
4552                 r_framedata_mem = next;
4553         }
4554 }
4555
4556 static void R_FrameData_Resize(qboolean mustgrow)
4557 {
4558         size_t wantedsize;
4559         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4560         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4561         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4562         {
4563                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4564                 newmem->wantedsize = wantedsize;
4565                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4566                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4567                 newmem->current = 0;
4568                 newmem->mark = 0;
4569                 newmem->purge = r_framedata_mem;
4570                 r_framedata_mem = newmem;
4571         }
4572 }
4573
4574 void R_FrameData_NewFrame(void)
4575 {
4576         R_FrameData_Resize(false);
4577         if (!r_framedata_mem)
4578                 return;
4579         // if we ran out of space on the last frame, free the old memory now
4580         while (r_framedata_mem->purge)
4581         {
4582                 // repeatedly remove the second item in the list, leaving only head
4583                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4584                 Mem_Free(r_framedata_mem->purge);
4585                 r_framedata_mem->purge = next;
4586         }
4587         // reset the current mem pointer
4588         r_framedata_mem->current = 0;
4589         r_framedata_mem->mark = 0;
4590 }
4591
4592 void *R_FrameData_Alloc(size_t size)
4593 {
4594         void *data;
4595         float newvalue;
4596
4597         // align to 16 byte boundary - the data pointer is already aligned, so we
4598         // only need to ensure the size of every allocation is also aligned
4599         size = (size + 15) & ~15;
4600
4601         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4602         {
4603                 // emergency - we ran out of space, allocate more memory
4604                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4605                 newvalue = r_framedatasize.value * 2.0f;
4606                 // 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
4607                 if (sizeof(size_t) >= 8)
4608                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4609                 else
4610                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4611                 // this might not be a growing it, but we'll allocate another buffer every time
4612                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4613                 R_FrameData_Resize(true);
4614         }
4615
4616         data = r_framedata_mem->data + r_framedata_mem->current;
4617         r_framedata_mem->current += size;
4618
4619         // count the usage for stats
4620         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4621         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4622
4623         return (void *)data;
4624 }
4625
4626 void *R_FrameData_Store(size_t size, void *data)
4627 {
4628         void *d = R_FrameData_Alloc(size);
4629         if (d && data)
4630                 memcpy(d, data, size);
4631         return d;
4632 }
4633
4634 void R_FrameData_SetMark(void)
4635 {
4636         if (!r_framedata_mem)
4637                 return;
4638         r_framedata_mem->mark = r_framedata_mem->current;
4639 }
4640
4641 void R_FrameData_ReturnToMark(void)
4642 {
4643         if (!r_framedata_mem)
4644                 return;
4645         r_framedata_mem->current = r_framedata_mem->mark;
4646 }
4647
4648 //==================================================================================
4649
4650 // avoid reusing the same buffer objects on consecutive frames
4651 #define R_BUFFERDATA_CYCLE 3
4652
4653 typedef struct r_bufferdata_buffer_s
4654 {
4655         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4656         size_t size; // how much usable space
4657         size_t current; // how much space in use
4658         r_meshbuffer_t *buffer; // the buffer itself
4659 }
4660 r_bufferdata_buffer_t;
4661
4662 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4663 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4664
4665 /// frees all dynamic buffers
4666 void R_BufferData_Reset(void)
4667 {
4668         int cycle, type;
4669         r_bufferdata_buffer_t **p, *mem;
4670         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4671         {
4672                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4673                 {
4674                         // free all buffers
4675                         p = &r_bufferdata_buffer[cycle][type];
4676                         while (*p)
4677                         {
4678                                 mem = *p;
4679                                 *p = (*p)->purge;
4680                                 if (mem->buffer)
4681                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4682                                 Mem_Free(mem);
4683                         }
4684                 }
4685         }
4686 }
4687
4688 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4689 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4690 {
4691         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4692         size_t size;
4693         float newvalue = r_buffermegs[type].value;
4694
4695         // increase the cvar if we have to (but only if we already have a mem)
4696         if (mustgrow && mem)
4697                 newvalue *= 2.0f;
4698         newvalue = bound(0.25f, newvalue, 256.0f);
4699         while (newvalue * 1024*1024 < minsize)
4700                 newvalue *= 2.0f;
4701
4702         // clamp the cvar to valid range
4703         newvalue = bound(0.25f, newvalue, 256.0f);
4704         if (r_buffermegs[type].value != newvalue)
4705                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4706
4707         // calculate size in bytes
4708         size = (size_t)(newvalue * 1024*1024);
4709         size = bound(131072, size, 256*1024*1024);
4710
4711         // allocate a new buffer if the size is different (purge old one later)
4712         // or if we were told we must grow the buffer
4713         if (!mem || mem->size != size || mustgrow)
4714         {
4715                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4716                 mem->size = size;
4717                 mem->current = 0;
4718                 if (type == R_BUFFERDATA_VERTEX)
4719                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4720                 else if (type == R_BUFFERDATA_INDEX16)
4721                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4722                 else if (type == R_BUFFERDATA_INDEX32)
4723                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4724                 else if (type == R_BUFFERDATA_UNIFORM)
4725                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4726                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4727                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4728         }
4729 }
4730
4731 void R_BufferData_NewFrame(void)
4732 {
4733         int type;
4734         r_bufferdata_buffer_t **p, *mem;
4735         // cycle to the next frame's buffers
4736         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4737         // if we ran out of space on the last time we used these buffers, free the old memory now
4738         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4739         {
4740                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4741                 {
4742                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4743                         // free all but the head buffer, this is how we recycle obsolete
4744                         // buffers after they are no longer in use
4745                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4746                         while (*p)
4747                         {
4748                                 mem = *p;
4749                                 *p = (*p)->purge;
4750                                 if (mem->buffer)
4751                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4752                                 Mem_Free(mem);
4753                         }
4754                         // reset the current offset
4755                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4756                 }
4757         }
4758 }
4759
4760 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4761 {
4762         r_bufferdata_buffer_t *mem;
4763         int offset = 0;
4764         int padsize;
4765
4766         *returnbufferoffset = 0;
4767
4768         // align size to a byte boundary appropriate for the buffer type, this
4769         // makes all allocations have aligned start offsets
4770         if (type == R_BUFFERDATA_UNIFORM)
4771                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4772         else
4773                 padsize = (datasize + 15) & ~15;
4774
4775         // if we ran out of space in this buffer we must allocate a new one
4776         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)
4777                 R_BufferData_Resize(type, true, padsize);
4778
4779         // if the resize did not give us enough memory, fail
4780         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)
4781                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4782
4783         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4784         offset = (int)mem->current;
4785         mem->current += padsize;
4786
4787         // upload the data to the buffer at the chosen offset
4788         if (offset == 0)
4789                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4790         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4791
4792         // count the usage for stats
4793         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4794         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4795
4796         // return the buffer offset
4797         *returnbufferoffset = offset;
4798
4799         return mem->buffer;
4800 }
4801
4802 //==================================================================================
4803
4804 // LordHavoc: animcache originally written by Echon, rewritten since then
4805
4806 /**
4807  * Animation cache prevents re-generating mesh data for an animated model
4808  * multiple times in one frame for lighting, shadowing, reflections, etc.
4809  */
4810
4811 void R_AnimCache_Free(void)
4812 {
4813 }
4814
4815 void R_AnimCache_ClearCache(void)
4816 {
4817         int i;
4818         entity_render_t *ent;
4819
4820         for (i = 0;i < r_refdef.scene.numentities;i++)
4821         {
4822                 ent = r_refdef.scene.entities[i];
4823                 ent->animcache_vertex3f = NULL;
4824                 ent->animcache_vertex3f_vertexbuffer = NULL;
4825                 ent->animcache_vertex3f_bufferoffset = 0;
4826                 ent->animcache_normal3f = NULL;
4827                 ent->animcache_normal3f_vertexbuffer = NULL;
4828                 ent->animcache_normal3f_bufferoffset = 0;
4829                 ent->animcache_svector3f = NULL;
4830                 ent->animcache_svector3f_vertexbuffer = NULL;
4831                 ent->animcache_svector3f_bufferoffset = 0;
4832                 ent->animcache_tvector3f = NULL;
4833                 ent->animcache_tvector3f_vertexbuffer = NULL;
4834                 ent->animcache_tvector3f_bufferoffset = 0;
4835                 ent->animcache_vertexmesh = NULL;
4836                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4837                 ent->animcache_vertexmesh_bufferoffset = 0;
4838                 ent->animcache_skeletaltransform3x4 = NULL;
4839                 ent->animcache_skeletaltransform3x4buffer = NULL;
4840                 ent->animcache_skeletaltransform3x4offset = 0;
4841                 ent->animcache_skeletaltransform3x4size = 0;
4842         }
4843 }
4844
4845 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4846 {
4847         int i;
4848
4849         // check if we need the meshbuffers
4850         if (!vid.useinterleavedarrays)
4851                 return;
4852
4853         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4854                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4855         // TODO: upload vertexbuffer?
4856         if (ent->animcache_vertexmesh)
4857         {
4858                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4859                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4860                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4861                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4862                 for (i = 0;i < numvertices;i++)
4863                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4864                 if (ent->animcache_svector3f)
4865                         for (i = 0;i < numvertices;i++)
4866                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4867                 if (ent->animcache_tvector3f)
4868                         for (i = 0;i < numvertices;i++)
4869                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4870                 if (ent->animcache_normal3f)
4871                         for (i = 0;i < numvertices;i++)
4872                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4873         }
4874 }
4875
4876 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4877 {
4878         dp_model_t *model = ent->model;
4879         int numvertices;
4880
4881         // see if this ent is worth caching
4882         if (!model || !model->Draw || !model->AnimateVertices)
4883                 return false;
4884         // nothing to cache if it contains no animations and has no skeleton
4885         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4886                 return false;
4887         // see if it is already cached for gpuskeletal
4888         if (ent->animcache_skeletaltransform3x4)
4889                 return false;
4890         // see if it is already cached as a mesh
4891         if (ent->animcache_vertex3f)
4892         {
4893                 // check if we need to add normals or tangents
4894                 if (ent->animcache_normal3f)
4895                         wantnormals = false;
4896                 if (ent->animcache_svector3f)
4897                         wanttangents = false;
4898                 if (!wantnormals && !wanttangents)
4899                         return false;
4900         }
4901
4902         // check which kind of cache we need to generate
4903         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4904         {
4905                 // cache the skeleton so the vertex shader can use it
4906                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4907                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4908                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4909                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4910                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4911                 // note: this can fail if the buffer is at the grow limit
4912                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4913                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4914         }
4915         else if (ent->animcache_vertex3f)
4916         {
4917                 // mesh was already cached but we may need to add normals/tangents
4918                 // (this only happens with multiple views, reflections, cameras, etc)
4919                 if (wantnormals || wanttangents)
4920                 {
4921                         numvertices = model->surfmesh.num_vertices;
4922                         if (wantnormals)
4923                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4924                         if (wanttangents)
4925                         {
4926                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4927                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4928                         }
4929                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4930                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4931                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4932                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4933                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4934                 }
4935         }
4936         else
4937         {
4938                 // generate mesh cache
4939                 numvertices = model->surfmesh.num_vertices;
4940                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4941                 if (wantnormals)
4942                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4943                 if (wanttangents)
4944                 {
4945                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4946                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4947                 }
4948                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4949                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4950                 if (wantnormals || wanttangents)
4951                 {
4952                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4953                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4954                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4955                 }
4956                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4957                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4958                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4959         }
4960         return true;
4961 }
4962
4963 void R_AnimCache_CacheVisibleEntities(void)
4964 {
4965         int i;
4966         qboolean wantnormals = true;
4967         qboolean wanttangents = !r_showsurfaces.integer;
4968
4969         switch(vid.renderpath)
4970         {
4971         case RENDERPATH_GL20:
4972         case RENDERPATH_D3D9:
4973         case RENDERPATH_D3D10:
4974         case RENDERPATH_D3D11:
4975         case RENDERPATH_GLES2:
4976                 break;
4977         case RENDERPATH_GL11:
4978         case RENDERPATH_GL13:
4979         case RENDERPATH_GLES1:
4980                 wanttangents = false;
4981                 break;
4982         case RENDERPATH_SOFT:
4983                 break;
4984         }
4985
4986         if (r_shownormals.integer)
4987                 wanttangents = wantnormals = true;
4988
4989         // TODO: thread this
4990         // NOTE: R_PrepareRTLights() also caches entities
4991
4992         for (i = 0;i < r_refdef.scene.numentities;i++)
4993                 if (r_refdef.viewcache.entityvisible[i])
4994                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4995 }
4996
4997 //==================================================================================
4998
4999 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5000 {
5001         int i;
5002         vec3_t eyemins, eyemaxs;
5003         vec3_t boxmins, boxmaxs;
5004         vec3_t start;
5005         vec3_t end;
5006         dp_model_t *model = r_refdef.scene.worldmodel;
5007         static vec3_t positions[] = {
5008                 { 0.5f, 0.5f, 0.5f },
5009                 { 0.0f, 0.0f, 0.0f },
5010                 { 0.0f, 0.0f, 1.0f },
5011                 { 0.0f, 1.0f, 0.0f },
5012                 { 0.0f, 1.0f, 1.0f },
5013                 { 1.0f, 0.0f, 0.0f },
5014                 { 1.0f, 0.0f, 1.0f },
5015                 { 1.0f, 1.0f, 0.0f },
5016                 { 1.0f, 1.0f, 1.0f },
5017         };
5018
5019         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5020         if (numsamples < 0)
5021                 return true;
5022
5023         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5024         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5025                 return true;
5026
5027         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5028                 return true;
5029
5030         // expand the eye box a little
5031         eyemins[0] = eye[0] - eyejitter;
5032         eyemaxs[0] = eye[0] + eyejitter;
5033         eyemins[1] = eye[1] - eyejitter;
5034         eyemaxs[1] = eye[1] + eyejitter;
5035         eyemins[2] = eye[2] - eyejitter;
5036         eyemaxs[2] = eye[2] + eyejitter;
5037         // expand the box a little
5038         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5039         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5040         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5041         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5042         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5043         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5044
5045         // return true if eye overlaps enlarged box
5046         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5047                 return true;
5048
5049         // try specific positions in the box first - note that these can be cached
5050         if (r_cullentities_trace_entityocclusion.integer)
5051         {
5052                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5053                 {
5054                         VectorCopy(eye, start);
5055                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5056                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5057                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5058                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5059                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5060                         // not picky - if the trace ended anywhere in the box we're good
5061                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5062                                 return true;
5063                 }
5064         }
5065         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5066                 return true;
5067
5068         // try various random positions
5069         for (i = 0; i < numsamples; i++)
5070         {
5071                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5072                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5073                 if (r_cullentities_trace_entityocclusion.integer)
5074                 {
5075                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5076                         // not picky - if the trace ended anywhere in the box we're good
5077                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5078                                 return true;
5079                 }
5080                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5081                         return true;
5082         }
5083
5084         return false;
5085 }
5086
5087
5088 static void R_View_UpdateEntityVisible (void)
5089 {
5090         int i;
5091         int renderimask;
5092         int samples;
5093         entity_render_t *ent;
5094
5095         if (r_refdef.envmap || r_fb.water.hideplayer)
5096                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5097         else if (chase_active.integer || r_fb.water.renderingscene)
5098                 renderimask = RENDER_VIEWMODEL;
5099         else
5100                 renderimask = RENDER_EXTERIORMODEL;
5101         if (!r_drawviewmodel.integer)
5102                 renderimask |= RENDER_VIEWMODEL;
5103         if (!r_drawexteriormodel.integer)
5104                 renderimask |= RENDER_EXTERIORMODEL;
5105         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5106         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5107         {
5108                 // worldmodel can check visibility
5109                 for (i = 0;i < r_refdef.scene.numentities;i++)
5110                 {
5111                         ent = r_refdef.scene.entities[i];
5112                         if (!(ent->flags & renderimask))
5113                         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)))
5114                         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))
5115                                 r_refdef.viewcache.entityvisible[i] = true;
5116                 }
5117         }
5118         else
5119         {
5120                 // no worldmodel or it can't check visibility
5121                 for (i = 0;i < r_refdef.scene.numentities;i++)
5122                 {
5123                         ent = r_refdef.scene.entities[i];
5124                         if (!(ent->flags & renderimask))
5125                         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)))
5126                                 r_refdef.viewcache.entityvisible[i] = true;
5127                 }
5128         }
5129         if (r_cullentities_trace.integer)
5130         {
5131                 for (i = 0;i < r_refdef.scene.numentities;i++)
5132                 {
5133                         if (!r_refdef.viewcache.entityvisible[i])
5134                                 continue;
5135                         ent = r_refdef.scene.entities[i];
5136                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5137                         {
5138                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5139                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5140                                         ent->last_trace_visibility = realtime;
5141                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5142                                         r_refdef.viewcache.entityvisible[i] = 0;
5143                         }
5144                 }
5145         }
5146 }
5147
5148 /// only used if skyrendermasked, and normally returns false
5149 static int R_DrawBrushModelsSky (void)
5150 {
5151         int i, sky;
5152         entity_render_t *ent;
5153
5154         sky = false;
5155         for (i = 0;i < r_refdef.scene.numentities;i++)
5156         {
5157                 if (!r_refdef.viewcache.entityvisible[i])
5158                         continue;
5159                 ent = r_refdef.scene.entities[i];
5160                 if (!ent->model || !ent->model->DrawSky)
5161                         continue;
5162                 ent->model->DrawSky(ent);
5163                 sky = true;
5164         }
5165         return sky;
5166 }
5167
5168 static void R_DrawNoModel(entity_render_t *ent);
5169 static void R_DrawModels(void)
5170 {
5171         int i;
5172         entity_render_t *ent;
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                 r_refdef.stats[r_stat_entities]++;
5180                 /*
5181                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5182                 {
5183                         vec3_t f, l, u, o;
5184                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5185                         Con_Printf("R_DrawModels\n");
5186                         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]);
5187                         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);
5188                         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);
5189                 }
5190                 */
5191                 if (ent->model && ent->model->Draw != NULL)
5192                         ent->model->Draw(ent);
5193                 else
5194                         R_DrawNoModel(ent);
5195         }
5196 }
5197
5198 static void R_DrawModelsDepth(void)
5199 {
5200         int i;
5201         entity_render_t *ent;
5202
5203         for (i = 0;i < r_refdef.scene.numentities;i++)
5204         {
5205                 if (!r_refdef.viewcache.entityvisible[i])
5206                         continue;
5207                 ent = r_refdef.scene.entities[i];
5208                 if (ent->model && ent->model->DrawDepth != NULL)
5209                         ent->model->DrawDepth(ent);
5210         }
5211 }
5212
5213 static void R_DrawModelsDebug(void)
5214 {
5215         int i;
5216         entity_render_t *ent;
5217
5218         for (i = 0;i < r_refdef.scene.numentities;i++)
5219         {
5220                 if (!r_refdef.viewcache.entityvisible[i])
5221                         continue;
5222                 ent = r_refdef.scene.entities[i];
5223                 if (ent->model && ent->model->DrawDebug != NULL)
5224                         ent->model->DrawDebug(ent);
5225         }
5226 }
5227
5228 static void R_DrawModelsAddWaterPlanes(void)
5229 {
5230         int i;
5231         entity_render_t *ent;
5232
5233         for (i = 0;i < r_refdef.scene.numentities;i++)
5234         {
5235                 if (!r_refdef.viewcache.entityvisible[i])
5236                         continue;
5237                 ent = r_refdef.scene.entities[i];
5238                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5239                         ent->model->DrawAddWaterPlanes(ent);
5240         }
5241 }
5242
5243 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}};
5244
5245 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5246 {
5247         if (r_hdr_irisadaptation.integer)
5248         {
5249                 vec3_t p;
5250                 vec3_t ambient;
5251                 vec3_t diffuse;
5252                 vec3_t diffusenormal;
5253                 vec3_t forward;
5254                 vec_t brightness = 0.0f;
5255                 vec_t goal;
5256                 vec_t current;
5257                 vec_t d;
5258                 int c;
5259                 VectorCopy(r_refdef.view.forward, forward);
5260                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5261                 {
5262                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5263                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5264                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5265                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5266                         d = DotProduct(forward, diffusenormal);
5267                         brightness += VectorLength(ambient);
5268                         if (d > 0)
5269                                 brightness += d * VectorLength(diffuse);
5270                 }
5271                 brightness *= 1.0f / c;
5272                 brightness += 0.00001f; // make sure it's never zero
5273                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5274                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5275                 current = r_hdr_irisadaptation_value.value;
5276                 if (current < goal)
5277                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5278                 else if (current > goal)
5279                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5280                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5281                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5282         }
5283         else if (r_hdr_irisadaptation_value.value != 1.0f)
5284                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5285 }
5286
5287 static void R_View_SetFrustum(const int *scissor)
5288 {
5289         int i;
5290         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5291         vec3_t forward, left, up, origin, v;
5292
5293         if(scissor)
5294         {
5295                 // flipped x coordinates (because x points left here)
5296                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5297                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5298
5299                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5300                 switch(vid.renderpath)
5301                 {
5302                         case RENDERPATH_D3D9:
5303                         case RENDERPATH_D3D10:
5304                         case RENDERPATH_D3D11:
5305                                 // non-flipped y coordinates
5306                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5307                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5308                                 break;
5309                         case RENDERPATH_SOFT:
5310                         case RENDERPATH_GL11:
5311                         case RENDERPATH_GL13:
5312                         case RENDERPATH_GL20:
5313                         case RENDERPATH_GLES1:
5314                         case RENDERPATH_GLES2:
5315                                 // non-flipped y coordinates
5316                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5317                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5318                                 break;
5319                 }
5320         }
5321
5322         // we can't trust r_refdef.view.forward and friends in reflected scenes
5323         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5324
5325 #if 0
5326         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5327         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5328         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5329         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5330         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5331         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5332         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5333         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5334         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5335         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5336         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5337         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5338 #endif
5339
5340 #if 0
5341         zNear = r_refdef.nearclip;
5342         nudge = 1.0 - 1.0 / (1<<23);
5343         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5344         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5345         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5346         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5347         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5348         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5349         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5350         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5351 #endif
5352
5353
5354
5355 #if 0
5356         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5357         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5358         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5359         r_refdef.view.frustum[0].dist = m[15] - m[12];
5360
5361         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5362         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5363         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5364         r_refdef.view.frustum[1].dist = m[15] + m[12];
5365
5366         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5367         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5368         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5369         r_refdef.view.frustum[2].dist = m[15] - m[13];
5370
5371         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5372         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5373         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5374         r_refdef.view.frustum[3].dist = m[15] + m[13];
5375
5376         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5377         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5378         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5379         r_refdef.view.frustum[4].dist = m[15] - m[14];
5380
5381         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5382         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5383         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5384         r_refdef.view.frustum[5].dist = m[15] + m[14];
5385 #endif
5386
5387         if (r_refdef.view.useperspective)
5388         {
5389                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5390                 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]);
5391                 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]);
5392                 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]);
5393                 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]);
5394
5395                 // then the normals from the corners relative to origin
5396                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5397                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5398                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5399                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5400
5401                 // in a NORMAL view, forward cross left == up
5402                 // in a REFLECTED view, forward cross left == down
5403                 // so our cross products above need to be adjusted for a left handed coordinate system
5404                 CrossProduct(forward, left, v);
5405                 if(DotProduct(v, up) < 0)
5406                 {
5407                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5408                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5409                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5410                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5411                 }
5412
5413                 // Leaving those out was a mistake, those were in the old code, and they
5414                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5415                 // I couldn't reproduce it after adding those normalizations. --blub
5416                 VectorNormalize(r_refdef.view.frustum[0].normal);
5417                 VectorNormalize(r_refdef.view.frustum[1].normal);
5418                 VectorNormalize(r_refdef.view.frustum[2].normal);
5419                 VectorNormalize(r_refdef.view.frustum[3].normal);
5420
5421                 // make the corners absolute
5422                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5423                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5424                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5425                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5426
5427                 // one more normal
5428                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5429
5430                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5431                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5432                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5433                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5434                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5435         }
5436         else
5437         {
5438                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5439                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5440                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5441                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5442                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5443                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5444                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5445                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5446                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5447                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5448         }
5449         r_refdef.view.numfrustumplanes = 5;
5450
5451         if (r_refdef.view.useclipplane)
5452         {
5453                 r_refdef.view.numfrustumplanes = 6;
5454                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5455         }
5456
5457         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5458                 PlaneClassify(r_refdef.view.frustum + i);
5459
5460         // LordHavoc: note to all quake engine coders, Quake had a special case
5461         // for 90 degrees which assumed a square view (wrong), so I removed it,
5462         // Quake2 has it disabled as well.
5463
5464         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5465         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5466         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5467         //PlaneClassify(&frustum[0]);
5468
5469         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5470         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5471         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5472         //PlaneClassify(&frustum[1]);
5473
5474         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5475         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5476         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5477         //PlaneClassify(&frustum[2]);
5478
5479         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5480         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5481         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5482         //PlaneClassify(&frustum[3]);
5483
5484         // nearclip plane
5485         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5486         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5487         //PlaneClassify(&frustum[4]);
5488 }
5489
5490 static void R_View_UpdateWithScissor(const int *myscissor)
5491 {
5492         R_Main_ResizeViewCache();
5493         R_View_SetFrustum(myscissor);
5494         R_View_WorldVisibility(r_refdef.view.useclipplane);
5495         R_View_UpdateEntityVisible();
5496 }
5497
5498 static void R_View_Update(void)
5499 {
5500         R_Main_ResizeViewCache();
5501         R_View_SetFrustum(NULL);
5502         R_View_WorldVisibility(r_refdef.view.useclipplane);
5503         R_View_UpdateEntityVisible();
5504 }
5505
5506 float viewscalefpsadjusted = 1.0f;
5507
5508 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5509 {
5510         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5511         scale = bound(0.03125f, scale, 1.0f);
5512         *outwidth = (int)ceil(width * scale);
5513         *outheight = (int)ceil(height * scale);
5514 }
5515
5516 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5517 {
5518         const float *customclipplane = NULL;
5519         float plane[4];
5520         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5521         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5522         {
5523                 // LordHavoc: couldn't figure out how to make this approach the
5524                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5525                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5526                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5527                         dist = r_refdef.view.clipplane.dist;
5528                 plane[0] = r_refdef.view.clipplane.normal[0];
5529                 plane[1] = r_refdef.view.clipplane.normal[1];
5530                 plane[2] = r_refdef.view.clipplane.normal[2];
5531                 plane[3] = -dist;
5532                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5533         }
5534
5535         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5536         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5537
5538         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5539         if (!r_refdef.view.useperspective)
5540                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5541         else if (vid.stencil && r_useinfinitefarclip.integer)
5542                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5543         else
5544                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5545         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5546         R_SetViewport(&r_refdef.view.viewport);
5547         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5548         {
5549                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5550                 float screenplane[4];
5551                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5552                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5553                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5554                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5555                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5556         }
5557 }
5558
5559 void R_EntityMatrix(const matrix4x4_t *matrix)
5560 {
5561         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5562         {
5563                 gl_modelmatrixchanged = false;
5564                 gl_modelmatrix = *matrix;
5565                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5566                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5567                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5568                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5569                 CHECKGLERROR
5570                 switch(vid.renderpath)
5571                 {
5572                 case RENDERPATH_D3D9:
5573 #ifdef SUPPORTD3D
5574                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5575                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5576 #endif
5577                         break;
5578                 case RENDERPATH_D3D10:
5579                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5580                         break;
5581                 case RENDERPATH_D3D11:
5582                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5583                         break;
5584                 case RENDERPATH_GL11:
5585                 case RENDERPATH_GL13:
5586                 case RENDERPATH_GLES1:
5587 #ifndef USE_GLES2
5588                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5589 #endif
5590                         break;
5591                 case RENDERPATH_SOFT:
5592                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5593                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5594                         break;
5595                 case RENDERPATH_GL20:
5596                 case RENDERPATH_GLES2:
5597                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5598                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5599                         break;
5600                 }
5601         }
5602 }
5603
5604 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5605 {
5606         r_viewport_t viewport;
5607
5608         CHECKGLERROR
5609
5610         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5611         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5612         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5613         R_SetViewport(&viewport);
5614         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5615         GL_Color(1, 1, 1, 1);
5616         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5617         GL_BlendFunc(GL_ONE, GL_ZERO);
5618         GL_ScissorTest(false);
5619         GL_DepthMask(false);
5620         GL_DepthRange(0, 1);
5621         GL_DepthTest(false);
5622         GL_DepthFunc(GL_LEQUAL);
5623         R_EntityMatrix(&identitymatrix);
5624         R_Mesh_ResetTextureState();
5625         GL_PolygonOffset(0, 0);
5626         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5627         switch(vid.renderpath)
5628         {
5629         case RENDERPATH_GL11:
5630         case RENDERPATH_GL13:
5631         case RENDERPATH_GL20:
5632         case RENDERPATH_GLES1:
5633         case RENDERPATH_GLES2:
5634                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5635                 break;
5636         case RENDERPATH_D3D9:
5637         case RENDERPATH_D3D10:
5638         case RENDERPATH_D3D11:
5639         case RENDERPATH_SOFT:
5640                 break;
5641         }
5642         GL_CullFace(GL_NONE);
5643
5644         CHECKGLERROR
5645 }
5646
5647 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5648 {
5649         DrawQ_Finish();
5650
5651         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5652 }
5653
5654 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5655 {
5656         DrawQ_Finish();
5657
5658         R_SetupView(true, fbo, depthtexture, colortexture);
5659         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5660         GL_Color(1, 1, 1, 1);
5661         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5662         GL_BlendFunc(GL_ONE, GL_ZERO);
5663         GL_ScissorTest(true);
5664         GL_DepthMask(true);
5665         GL_DepthRange(0, 1);
5666         GL_DepthTest(true);
5667         GL_DepthFunc(GL_LEQUAL);
5668         R_EntityMatrix(&identitymatrix);
5669         R_Mesh_ResetTextureState();
5670         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5671         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5672         switch(vid.renderpath)
5673         {
5674         case RENDERPATH_GL11:
5675         case RENDERPATH_GL13:
5676         case RENDERPATH_GL20:
5677         case RENDERPATH_GLES1:
5678         case RENDERPATH_GLES2:
5679                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5680                 break;
5681         case RENDERPATH_D3D9:
5682         case RENDERPATH_D3D10:
5683         case RENDERPATH_D3D11:
5684         case RENDERPATH_SOFT:
5685                 break;
5686         }
5687         GL_CullFace(r_refdef.view.cullface_back);
5688 }
5689
5690 /*
5691 ================
5692 R_RenderView_UpdateViewVectors
5693 ================
5694 */
5695 void R_RenderView_UpdateViewVectors(void)
5696 {
5697         // break apart the view matrix into vectors for various purposes
5698         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5699         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5700         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5701         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5702         // make an inverted copy of the view matrix for tracking sprites
5703         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5704 }
5705
5706 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5707 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5708
5709 static void R_Water_StartFrame(void)
5710 {
5711         int i;
5712         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5713         r_waterstate_waterplane_t *p;
5714         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5715
5716         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5717                 return;
5718
5719         switch(vid.renderpath)
5720         {
5721         case RENDERPATH_GL20:
5722         case RENDERPATH_D3D9:
5723         case RENDERPATH_D3D10:
5724         case RENDERPATH_D3D11:
5725         case RENDERPATH_SOFT:
5726         case RENDERPATH_GLES2:
5727                 break;
5728         case RENDERPATH_GL11:
5729         case RENDERPATH_GL13:
5730         case RENDERPATH_GLES1:
5731                 return;
5732         }
5733
5734         // set waterwidth and waterheight to the water resolution that will be
5735         // used (often less than the screen resolution for faster rendering)
5736         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5737
5738         // calculate desired texture sizes
5739         // can't use water if the card does not support the texture size
5740         if (!r_water.integer || r_showsurfaces.integer)
5741                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5742         else if (vid.support.arb_texture_non_power_of_two)
5743         {
5744                 texturewidth = waterwidth;
5745                 textureheight = waterheight;
5746                 camerawidth = waterwidth;
5747                 cameraheight = waterheight;
5748         }
5749         else
5750         {
5751                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5752                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5753                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5754                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5755         }
5756
5757         // allocate textures as needed
5758         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5759         {
5760                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5761                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5762                 {
5763                         if (p->texture_refraction)
5764                                 R_FreeTexture(p->texture_refraction);
5765                         p->texture_refraction = NULL;
5766                         if (p->fbo_refraction)
5767                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5768                         p->fbo_refraction = 0;
5769                         if (p->texture_reflection)
5770                                 R_FreeTexture(p->texture_reflection);
5771                         p->texture_reflection = NULL;
5772                         if (p->fbo_reflection)
5773                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5774                         p->fbo_reflection = 0;
5775                         if (p->texture_camera)
5776                                 R_FreeTexture(p->texture_camera);
5777                         p->texture_camera = NULL;
5778                         if (p->fbo_camera)
5779                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5780                         p->fbo_camera = 0;
5781                 }
5782                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5783                 r_fb.water.texturewidth = texturewidth;
5784                 r_fb.water.textureheight = textureheight;
5785                 r_fb.water.camerawidth = camerawidth;
5786                 r_fb.water.cameraheight = cameraheight;
5787         }
5788
5789         if (r_fb.water.texturewidth)
5790         {
5791                 int scaledwidth, scaledheight;
5792
5793                 r_fb.water.enabled = true;
5794
5795                 // water resolution is usually reduced
5796                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5797                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5798                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5799
5800                 // set up variables that will be used in shader setup
5801                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5802                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5803                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5804                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5805         }
5806
5807         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5808         r_fb.water.numwaterplanes = 0;
5809 }
5810
5811 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5812 {
5813         int planeindex, bestplaneindex, vertexindex;
5814         vec3_t mins, maxs, normal, center, v, n;
5815         vec_t planescore, bestplanescore;
5816         mplane_t plane;
5817         r_waterstate_waterplane_t *p;
5818         texture_t *t = R_GetCurrentTexture(surface->texture);
5819
5820         rsurface.texture = t;
5821         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5822         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5823         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5824                 return;
5825         // average the vertex normals, find the surface bounds (after deformvertexes)
5826         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5827         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5828         VectorCopy(n, normal);
5829         VectorCopy(v, mins);
5830         VectorCopy(v, maxs);
5831         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5832         {
5833                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5834                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5835                 VectorAdd(normal, n, normal);
5836                 mins[0] = min(mins[0], v[0]);
5837                 mins[1] = min(mins[1], v[1]);
5838                 mins[2] = min(mins[2], v[2]);
5839                 maxs[0] = max(maxs[0], v[0]);
5840                 maxs[1] = max(maxs[1], v[1]);
5841                 maxs[2] = max(maxs[2], v[2]);
5842         }
5843         VectorNormalize(normal);
5844         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5845
5846         VectorCopy(normal, plane.normal);
5847         VectorNormalize(plane.normal);
5848         plane.dist = DotProduct(center, plane.normal);
5849         PlaneClassify(&plane);
5850         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5851         {
5852                 // skip backfaces (except if nocullface is set)
5853 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5854 //                      return;
5855                 VectorNegate(plane.normal, plane.normal);
5856                 plane.dist *= -1;
5857                 PlaneClassify(&plane);
5858         }
5859
5860
5861         // find a matching plane if there is one
5862         bestplaneindex = -1;
5863         bestplanescore = 1048576.0f;
5864         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5865         {
5866                 if(p->camera_entity == t->camera_entity)
5867                 {
5868                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5869                         if (bestplaneindex < 0 || bestplanescore > planescore)
5870                         {
5871                                 bestplaneindex = planeindex;
5872                                 bestplanescore = planescore;
5873                         }
5874                 }
5875         }
5876         planeindex = bestplaneindex;
5877
5878         // if this surface does not fit any known plane rendered this frame, add one
5879         if (planeindex < 0 || bestplanescore > 0.001f)
5880         {
5881                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5882                 {
5883                         // store the new plane
5884                         planeindex = r_fb.water.numwaterplanes++;
5885                         p = r_fb.water.waterplanes + planeindex;
5886                         p->plane = plane;
5887                         // clear materialflags and pvs
5888                         p->materialflags = 0;
5889                         p->pvsvalid = false;
5890                         p->camera_entity = t->camera_entity;
5891                         VectorCopy(mins, p->mins);
5892                         VectorCopy(maxs, p->maxs);
5893                 }
5894                 else
5895                 {
5896                         // We're totally screwed.
5897                         return;
5898                 }
5899         }
5900         else
5901         {
5902                 // merge mins/maxs when we're adding this surface to the plane
5903                 p = r_fb.water.waterplanes + planeindex;
5904                 p->mins[0] = min(p->mins[0], mins[0]);
5905                 p->mins[1] = min(p->mins[1], mins[1]);
5906                 p->mins[2] = min(p->mins[2], mins[2]);
5907                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5908                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5909                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5910         }
5911         // merge this surface's materialflags into the waterplane
5912         p->materialflags |= t->currentmaterialflags;
5913         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5914         {
5915                 // merge this surface's PVS into the waterplane
5916                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5917                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5918                 {
5919                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5920                         p->pvsvalid = true;
5921                 }
5922         }
5923 }
5924
5925 extern cvar_t r_drawparticles;
5926 extern cvar_t r_drawdecals;
5927
5928 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5929 {
5930         int myscissor[4];
5931         r_refdef_view_t originalview;
5932         r_refdef_view_t myview;
5933         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;
5934         r_waterstate_waterplane_t *p;
5935         vec3_t visorigin;
5936         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5937         char vabuf[1024];
5938
5939         originalview = r_refdef.view;
5940
5941         // lowquality hack, temporarily shut down some cvars and restore afterwards
5942         qualityreduction = r_water_lowquality.integer;
5943         if (qualityreduction > 0)
5944         {
5945                 if (qualityreduction >= 1)
5946                 {
5947                         old_r_shadows = r_shadows.integer;
5948                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5949                         old_r_dlight = r_shadow_realtime_dlight.integer;
5950                         Cvar_SetValueQuick(&r_shadows, 0);
5951                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5952                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5953                 }
5954                 if (qualityreduction >= 2)
5955                 {
5956                         old_r_dynamic = r_dynamic.integer;
5957                         old_r_particles = r_drawparticles.integer;
5958                         old_r_decals = r_drawdecals.integer;
5959                         Cvar_SetValueQuick(&r_dynamic, 0);
5960                         Cvar_SetValueQuick(&r_drawparticles, 0);
5961                         Cvar_SetValueQuick(&r_drawdecals, 0);
5962                 }
5963         }
5964
5965         // make sure enough textures are allocated
5966         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5967         {
5968                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
5969                         continue;
5970                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5971                 {
5972                         if (!p->texture_refraction)
5973                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5974                         if (!p->texture_refraction)
5975                                 goto error;
5976                         if (usewaterfbo)
5977                         {
5978                                 if (r_fb.water.depthtexture == NULL)
5979                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5980                                 if (p->fbo_refraction == 0)
5981                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5982                         }
5983                 }
5984                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5985                 {
5986                         if (!p->texture_camera)
5987                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5988                         if (!p->texture_camera)
5989                                 goto error;
5990                         if (usewaterfbo)
5991                         {
5992                                 if (r_fb.water.depthtexture == NULL)
5993                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5994                                 if (p->fbo_camera == 0)
5995                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5996                         }
5997                 }
5998
5999                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6000                 {
6001                         if (!p->texture_reflection)
6002                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6003                         if (!p->texture_reflection)
6004                                 goto error;
6005                         if (usewaterfbo)
6006                         {
6007                                 if (r_fb.water.depthtexture == NULL)
6008                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6009                                 if (p->fbo_reflection == 0)
6010                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6011                         }
6012                 }
6013         }
6014
6015         // render views
6016         r_refdef.view = originalview;
6017         r_refdef.view.showdebug = false;
6018         r_refdef.view.width = r_fb.water.waterwidth;
6019         r_refdef.view.height = r_fb.water.waterheight;
6020         r_refdef.view.useclipplane = true;
6021         myview = r_refdef.view;
6022         r_fb.water.renderingscene = true;
6023         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6024         {
6025                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6026                         continue;
6027                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6028                 {
6029                         r_refdef.view = myview;
6030                         if(r_water_scissormode.integer)
6031                         {
6032                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6033                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6034                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6035                         }
6036
6037                         // render reflected scene and copy into texture
6038                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6039                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6040                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6041                         r_refdef.view.clipplane = p->plane;
6042                         // reverse the cullface settings for this render
6043                         r_refdef.view.cullface_front = GL_FRONT;
6044                         r_refdef.view.cullface_back = GL_BACK;
6045                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6046                         {
6047                                 r_refdef.view.usecustompvs = true;
6048                                 if (p->pvsvalid)
6049                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6050                                 else
6051                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6052                         }
6053
6054                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6055                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6056                         R_ClearScreen(r_refdef.fogenabled);
6057                         if(r_water_scissormode.integer & 2)
6058                                 R_View_UpdateWithScissor(myscissor);
6059                         else
6060                                 R_View_Update();
6061                         R_AnimCache_CacheVisibleEntities();
6062                         if(r_water_scissormode.integer & 1)
6063                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6064                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6065
6066                         if (!p->fbo_reflection)
6067                                 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6068                         r_fb.water.hideplayer = false;
6069                 }
6070
6071                 // render the normal view scene and copy into texture
6072                 // (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)
6073                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6074                 {
6075                         r_refdef.view = myview;
6076                         if(r_water_scissormode.integer)
6077                         {
6078                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6079                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6080                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6081                         }
6082
6083                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6084
6085                         r_refdef.view.clipplane = p->plane;
6086                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6087                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6088
6089                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6090                         {
6091                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6092                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6093                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6094                                 R_RenderView_UpdateViewVectors();
6095                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6096                                 {
6097                                         r_refdef.view.usecustompvs = true;
6098                                         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);
6099                                 }
6100                         }
6101
6102                         PlaneClassify(&r_refdef.view.clipplane);
6103
6104                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6105                         R_ClearScreen(r_refdef.fogenabled);
6106                         if(r_water_scissormode.integer & 2)
6107                                 R_View_UpdateWithScissor(myscissor);
6108                         else
6109                                 R_View_Update();
6110                         R_AnimCache_CacheVisibleEntities();
6111                         if(r_water_scissormode.integer & 1)
6112                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6113                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6114
6115                         if (!p->fbo_refraction)
6116                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6117                         r_fb.water.hideplayer = false;
6118                 }
6119                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6120                 {
6121                         r_refdef.view = myview;
6122
6123                         r_refdef.view.clipplane = p->plane;
6124                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6125                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6126
6127                         r_refdef.view.width = r_fb.water.camerawidth;
6128                         r_refdef.view.height = r_fb.water.cameraheight;
6129                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6130                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6131                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6132                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6133
6134                         if(p->camera_entity)
6135                         {
6136                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6137                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6138                         }
6139
6140                         // note: all of the view is used for displaying... so
6141                         // there is no use in scissoring
6142
6143                         // reverse the cullface settings for this render
6144                         r_refdef.view.cullface_front = GL_FRONT;
6145                         r_refdef.view.cullface_back = GL_BACK;
6146                         // also reverse the view matrix
6147                         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
6148                         R_RenderView_UpdateViewVectors();
6149                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6150                         {
6151                                 r_refdef.view.usecustompvs = true;
6152                                 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);
6153                         }
6154                         
6155                         // camera needs no clipplane
6156                         r_refdef.view.useclipplane = false;
6157
6158                         PlaneClassify(&r_refdef.view.clipplane);
6159
6160                         r_fb.water.hideplayer = false;
6161
6162                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6163                         R_ClearScreen(r_refdef.fogenabled);
6164                         R_View_Update();
6165                         R_AnimCache_CacheVisibleEntities();
6166                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6167
6168                         if (!p->fbo_camera)
6169                                 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6170                         r_fb.water.hideplayer = false;
6171                 }
6172
6173         }
6174         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6175         r_fb.water.renderingscene = false;
6176         r_refdef.view = originalview;
6177         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6178         if (!r_fb.water.depthtexture)
6179                 R_ClearScreen(r_refdef.fogenabled);
6180         R_View_Update();
6181         R_AnimCache_CacheVisibleEntities();
6182         goto finish;
6183 error:
6184         r_refdef.view = originalview;
6185         r_fb.water.renderingscene = false;
6186         Cvar_SetValueQuick(&r_water, 0);
6187         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6188 finish:
6189         // lowquality hack, restore cvars
6190         if (qualityreduction > 0)
6191         {
6192                 if (qualityreduction >= 1)
6193                 {
6194                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6195                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6196                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6197                 }
6198                 if (qualityreduction >= 2)
6199                 {
6200                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6201                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6202                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6203                 }
6204         }
6205 }
6206
6207 static void R_Bloom_StartFrame(void)
6208 {
6209         int i;
6210         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6211         int viewwidth, viewheight;
6212         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6213         textype_t textype = TEXTYPE_COLORBUFFER;
6214
6215         switch (vid.renderpath)
6216         {
6217         case RENDERPATH_GL20:
6218                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6219                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6220                 {
6221                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6222                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6223                 }
6224                 break;
6225         case RENDERPATH_GL11:
6226         case RENDERPATH_GL13:
6227         case RENDERPATH_GLES1:
6228                 return; // don't bother
6229         case RENDERPATH_GLES2:
6230         case RENDERPATH_D3D9:
6231         case RENDERPATH_D3D10:
6232         case RENDERPATH_D3D11:
6233                 r_fb.usedepthtextures = false;
6234                 break;
6235         case RENDERPATH_SOFT:
6236                 r_fb.usedepthtextures = true;
6237                 break;
6238         }
6239
6240         if (r_viewscale_fpsscaling.integer)
6241         {
6242                 double actualframetime;
6243                 double targetframetime;
6244                 double adjust;
6245                 actualframetime = r_refdef.lastdrawscreentime;
6246                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6247                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6248                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6249                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6250                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6251                 viewscalefpsadjusted += adjust;
6252                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6253         }
6254         else
6255                 viewscalefpsadjusted = 1.0f;
6256
6257         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6258
6259         switch(vid.renderpath)
6260         {
6261         case RENDERPATH_GL20:
6262         case RENDERPATH_D3D9:
6263         case RENDERPATH_D3D10:
6264         case RENDERPATH_D3D11:
6265         case RENDERPATH_SOFT:
6266         case RENDERPATH_GLES2:
6267                 break;
6268         case RENDERPATH_GL11:
6269         case RENDERPATH_GL13:
6270         case RENDERPATH_GLES1:
6271                 return;
6272         }
6273
6274         // set bloomwidth and bloomheight to the bloom resolution that will be
6275         // used (often less than the screen resolution for faster rendering)
6276         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6277         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6278         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6279         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6280         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6281
6282         // calculate desired texture sizes
6283         if (vid.support.arb_texture_non_power_of_two)
6284         {
6285                 screentexturewidth = vid.width;
6286                 screentextureheight = vid.height;
6287                 bloomtexturewidth = r_fb.bloomwidth;
6288                 bloomtextureheight = r_fb.bloomheight;
6289         }
6290         else
6291         {
6292                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6293                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6294                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6295                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6296         }
6297
6298         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))
6299         {
6300                 Cvar_SetValueQuick(&r_bloom, 0);
6301                 Cvar_SetValueQuick(&r_motionblur, 0);
6302                 Cvar_SetValueQuick(&r_damageblur, 0);
6303         }
6304
6305         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6306          && !r_bloom.integer
6307          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6308          && !useviewfbo
6309          && r_viewscale.value == 1.0f
6310          && !r_viewscale_fpsscaling.integer)
6311                 screentexturewidth = screentextureheight = 0;
6312         if (!r_bloom.integer)
6313                 bloomtexturewidth = bloomtextureheight = 0;
6314
6315         // allocate textures as needed
6316         if (r_fb.screentexturewidth != screentexturewidth
6317          || r_fb.screentextureheight != screentextureheight
6318          || r_fb.bloomtexturewidth != bloomtexturewidth
6319          || r_fb.bloomtextureheight != bloomtextureheight
6320          || r_fb.textype != textype
6321          || useviewfbo != (r_fb.fbo != 0))
6322         {
6323                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6324                 {
6325                         if (r_fb.bloomtexture[i])
6326                                 R_FreeTexture(r_fb.bloomtexture[i]);
6327                         r_fb.bloomtexture[i] = NULL;
6328
6329                         if (r_fb.bloomfbo[i])
6330                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6331                         r_fb.bloomfbo[i] = 0;
6332                 }
6333
6334                 if (r_fb.fbo)
6335                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6336                 r_fb.fbo = 0;
6337
6338                 if (r_fb.colortexture)
6339                         R_FreeTexture(r_fb.colortexture);
6340                 r_fb.colortexture = NULL;
6341
6342                 if (r_fb.depthtexture)
6343                         R_FreeTexture(r_fb.depthtexture);
6344                 r_fb.depthtexture = NULL;
6345
6346                 if (r_fb.ghosttexture)
6347                         R_FreeTexture(r_fb.ghosttexture);
6348                 r_fb.ghosttexture = NULL;
6349
6350                 r_fb.screentexturewidth = screentexturewidth;
6351                 r_fb.screentextureheight = screentextureheight;
6352                 r_fb.bloomtexturewidth = bloomtexturewidth;
6353                 r_fb.bloomtextureheight = bloomtextureheight;
6354                 r_fb.textype = textype;
6355
6356                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6357                 {
6358                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6359                                 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);
6360                         r_fb.ghosttexture_valid = false;
6361                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6362                         if (useviewfbo)
6363                         {
6364                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6365                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6366                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6367                         }
6368                 }
6369
6370                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6371                 {
6372                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6373                         {
6374                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6375                                 if (useviewfbo)
6376                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6377                         }
6378                 }
6379         }
6380
6381         // bloom texture is a different resolution
6382         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6383         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6384         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6385         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6386         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6387
6388         // set up a texcoord array for the full resolution screen image
6389         // (we have to keep this around to copy back during final render)
6390         r_fb.screentexcoord2f[0] = 0;
6391         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6392         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6393         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6394         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6395         r_fb.screentexcoord2f[5] = 0;
6396         r_fb.screentexcoord2f[6] = 0;
6397         r_fb.screentexcoord2f[7] = 0;
6398
6399         if(r_fb.fbo) 
6400         {
6401                 for (i = 1;i < 8;i += 2)
6402                 {
6403                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6404                 }
6405         }
6406
6407         // set up a texcoord array for the reduced resolution bloom image
6408         // (which will be additive blended over the screen image)
6409         r_fb.bloomtexcoord2f[0] = 0;
6410         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6411         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6412         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6413         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6414         r_fb.bloomtexcoord2f[5] = 0;
6415         r_fb.bloomtexcoord2f[6] = 0;
6416         r_fb.bloomtexcoord2f[7] = 0;
6417
6418         switch(vid.renderpath)
6419         {
6420         case RENDERPATH_GL11:
6421         case RENDERPATH_GL13:
6422         case RENDERPATH_GL20:
6423         case RENDERPATH_SOFT:
6424         case RENDERPATH_GLES1:
6425         case RENDERPATH_GLES2:
6426                 break;
6427         case RENDERPATH_D3D9:
6428         case RENDERPATH_D3D10:
6429         case RENDERPATH_D3D11:
6430                 for (i = 0;i < 4;i++)
6431                 {
6432                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6433                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6434                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6435                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6436                 }
6437                 break;
6438         }
6439
6440         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6441
6442         if (r_fb.fbo)
6443                 r_refdef.view.clear = true;
6444 }
6445
6446 static void R_Bloom_MakeTexture(void)
6447 {
6448         int x, range, dir;
6449         float xoffset, yoffset, r, brighten;
6450         rtexture_t *intex;
6451         float colorscale = r_bloom_colorscale.value;
6452
6453         r_refdef.stats[r_stat_bloom]++;
6454     
6455 #if 0
6456     // this copy is unnecessary since it happens in R_BlendView already
6457         if (!r_fb.fbo)
6458         {
6459                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6460                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6461         }
6462 #endif
6463
6464         // scale down screen texture to the bloom texture size
6465         CHECKGLERROR
6466         r_fb.bloomindex = 0;
6467         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6468         R_SetViewport(&r_fb.bloomviewport);
6469         GL_CullFace(GL_NONE);
6470         GL_DepthTest(false);
6471         GL_BlendFunc(GL_ONE, GL_ZERO);
6472         GL_Color(colorscale, colorscale, colorscale, 1);
6473         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6474         switch(vid.renderpath)
6475         {
6476         case RENDERPATH_GL11:
6477         case RENDERPATH_GL13:
6478         case RENDERPATH_GL20:
6479         case RENDERPATH_GLES1:
6480         case RENDERPATH_GLES2:
6481         case RENDERPATH_SOFT:
6482                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6483                 break;
6484         case RENDERPATH_D3D9:
6485         case RENDERPATH_D3D10:
6486         case RENDERPATH_D3D11:
6487                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6488                 break;
6489         }
6490         // TODO: do boxfilter scale-down in shader?
6491         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6492         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6493         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6494
6495         // we now have a properly scaled bloom image
6496         if (!r_fb.bloomfbo[r_fb.bloomindex])
6497         {
6498                 // copy it into the bloom texture
6499                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6500                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6501         }
6502
6503         // multiply bloom image by itself as many times as desired
6504         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6505         {
6506                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6507                 r_fb.bloomindex ^= 1;
6508                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6509                 x *= 2;
6510                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6511                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6512                 {
6513                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6514                         GL_Color(r,r,r,1); // apply fix factor
6515                 }
6516                 else
6517                 {
6518                         if(x <= 2)
6519                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6520                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6521                         GL_Color(1,1,1,1); // no fix factor supported here
6522                 }
6523                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6524                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6525                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6526                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6527
6528                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6529                 {
6530                         // copy the darkened image to a texture
6531                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6532                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6533                 }
6534         }
6535
6536         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6537         brighten = r_bloom_brighten.value;
6538         brighten = sqrt(brighten);
6539         if(range >= 1)
6540                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6541
6542         for (dir = 0;dir < 2;dir++)
6543         {
6544                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6545                 r_fb.bloomindex ^= 1;
6546                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6547                 // blend on at multiple vertical offsets to achieve a vertical blur
6548                 // TODO: do offset blends using GLSL
6549                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6550                 GL_BlendFunc(GL_ONE, GL_ZERO);
6551                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6552                 for (x = -range;x <= range;x++)
6553                 {
6554                         if (!dir){xoffset = 0;yoffset = x;}
6555                         else {xoffset = x;yoffset = 0;}
6556                         xoffset /= (float)r_fb.bloomtexturewidth;
6557                         yoffset /= (float)r_fb.bloomtextureheight;
6558                         // compute a texcoord array with the specified x and y offset
6559                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6560                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6561                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6562                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6563                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6564                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6565                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6566                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6567                         // this r value looks like a 'dot' particle, fading sharply to
6568                         // black at the edges
6569                         // (probably not realistic but looks good enough)
6570                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6571                         //r = brighten/(range*2+1);
6572                         r = brighten / (range * 2 + 1);
6573                         if(range >= 1)
6574                                 r *= (1 - x*x/(float)(range*range));
6575                         GL_Color(r, r, r, 1);
6576                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6577                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6578                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6579                         GL_BlendFunc(GL_ONE, GL_ONE);
6580                 }
6581
6582                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6583                 {
6584                         // copy the vertically or horizontally blurred bloom view to a texture
6585                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6586                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6587                 }
6588         }
6589 }
6590
6591 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6592 {
6593         dpuint64 permutation;
6594         float uservecs[4][4];
6595
6596         R_EntityMatrix(&identitymatrix);
6597
6598         switch (vid.renderpath)
6599         {
6600         case RENDERPATH_GL20:
6601         case RENDERPATH_D3D9:
6602         case RENDERPATH_D3D10:
6603         case RENDERPATH_D3D11:
6604         case RENDERPATH_SOFT:
6605         case RENDERPATH_GLES2:
6606                 permutation =
6607                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6608                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6609                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6610                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6611                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6612
6613                 if (r_fb.colortexture)
6614                 {
6615                         if (!r_fb.fbo)
6616                         {
6617                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6618                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6619                         }
6620
6621                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6622                         {
6623                                 // declare variables
6624                                 float blur_factor, blur_mouseaccel, blur_velocity;
6625                                 static float blur_average; 
6626                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6627
6628                                 // set a goal for the factoring
6629                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6630                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6631                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6632                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6633                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6634                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6635
6636                                 // from the goal, pick an averaged value between goal and last value
6637                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6638                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6639
6640                                 // enforce minimum amount of blur 
6641                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6642
6643                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6644
6645                                 // calculate values into a standard alpha
6646                                 cl.motionbluralpha = 1 - exp(-
6647                                                 (
6648                                                  (r_motionblur.value * blur_factor / 80)
6649                                                  +
6650                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6651                                                 )
6652                                                 /
6653                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6654                                           );
6655
6656                                 // randomization for the blur value to combat persistent ghosting
6657                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6658                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6659
6660                                 // apply the blur
6661                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6662                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6663                                 {
6664                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6665                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6666                                         switch(vid.renderpath)
6667                                         {
6668                                         case RENDERPATH_GL11:
6669                                         case RENDERPATH_GL13:
6670                                         case RENDERPATH_GL20:
6671                                         case RENDERPATH_GLES1:
6672                                         case RENDERPATH_GLES2:
6673                                         case RENDERPATH_SOFT:
6674                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6675                                                 break;
6676                                         case RENDERPATH_D3D9:
6677                                         case RENDERPATH_D3D10:
6678                                         case RENDERPATH_D3D11:
6679                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6680                                                 break;
6681                                         }
6682                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6683                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6684                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6685                                 }
6686
6687                                 // updates old view angles for next pass
6688                                 VectorCopy(cl.viewangles, blur_oldangles);
6689
6690                                 // copy view into the ghost texture
6691                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6692                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6693                                 r_fb.ghosttexture_valid = true;
6694                         }
6695                 }
6696                 else
6697                 {
6698                         // no r_fb.colortexture means we're rendering to the real fb
6699                         // we may still have to do view tint...
6700                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6701                         {
6702                                 // apply a color tint to the whole view
6703                                 R_ResetViewRendering2D(0, NULL, NULL);
6704                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6705                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6706                                 R_SetupShader_Generic_NoTexture(false, true);
6707                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6708                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6709                         }
6710                         break; // no screen processing, no bloom, skip it
6711                 }
6712
6713                 if (r_fb.bloomtexture[0])
6714                 {
6715                         // make the bloom texture
6716                         R_Bloom_MakeTexture();
6717                 }
6718
6719 #if _MSC_VER >= 1400
6720 #define sscanf sscanf_s
6721 #endif
6722                 memset(uservecs, 0, sizeof(uservecs));
6723                 if (r_glsl_postprocess_uservec1_enable.integer)
6724                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6725                 if (r_glsl_postprocess_uservec2_enable.integer)
6726                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6727                 if (r_glsl_postprocess_uservec3_enable.integer)
6728                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6729                 if (r_glsl_postprocess_uservec4_enable.integer)
6730                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6731
6732                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6733                 GL_Color(1, 1, 1, 1);
6734                 GL_BlendFunc(GL_ONE, GL_ZERO);
6735
6736                 switch(vid.renderpath)
6737                 {
6738                 case RENDERPATH_GL20:
6739                 case RENDERPATH_GLES2:
6740                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6741                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6742                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6743                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6744                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6745                         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]);
6746                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6747                         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]);
6748                         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]);
6749                         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]);
6750                         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]);
6751                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6752                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6753                         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);
6754                         break;
6755                 case RENDERPATH_D3D9:
6756 #ifdef SUPPORTD3D
6757                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6758                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6759                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6760                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6761                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6762                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6763                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6764                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6765                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6766                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6767                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6768                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6769                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6770                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6771                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6772 #endif
6773                         break;
6774                 case RENDERPATH_D3D10:
6775                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6776                         break;
6777                 case RENDERPATH_D3D11:
6778                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6779                         break;
6780                 case RENDERPATH_SOFT:
6781                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6782                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6783                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6784                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6785                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6786                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6787                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6788                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6789                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6790                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6791                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6792                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6793                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6794                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6795                         break;
6796                 default:
6797                         break;
6798                 }
6799                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6800                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6801                 break;
6802         case RENDERPATH_GL11:
6803         case RENDERPATH_GL13:
6804         case RENDERPATH_GLES1:
6805                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6806                 {
6807                         // apply a color tint to the whole view
6808                         R_ResetViewRendering2D(0, NULL, NULL);
6809                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6810                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6811                         R_SetupShader_Generic_NoTexture(false, true);
6812                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6813                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6814                 }
6815                 break;
6816         }
6817 }
6818
6819 matrix4x4_t r_waterscrollmatrix;
6820
6821 void R_UpdateFog(void)
6822 {
6823         // Nehahra fog
6824         if (gamemode == GAME_NEHAHRA)
6825         {
6826                 if (gl_fogenable.integer)
6827                 {
6828                         r_refdef.oldgl_fogenable = true;
6829                         r_refdef.fog_density = gl_fogdensity.value;
6830                         r_refdef.fog_red = gl_fogred.value;
6831                         r_refdef.fog_green = gl_foggreen.value;
6832                         r_refdef.fog_blue = gl_fogblue.value;
6833                         r_refdef.fog_alpha = 1;
6834                         r_refdef.fog_start = 0;
6835                         r_refdef.fog_end = gl_skyclip.value;
6836                         r_refdef.fog_height = 1<<30;
6837                         r_refdef.fog_fadedepth = 128;
6838                 }
6839                 else if (r_refdef.oldgl_fogenable)
6840                 {
6841                         r_refdef.oldgl_fogenable = false;
6842                         r_refdef.fog_density = 0;
6843                         r_refdef.fog_red = 0;
6844                         r_refdef.fog_green = 0;
6845                         r_refdef.fog_blue = 0;
6846                         r_refdef.fog_alpha = 0;
6847                         r_refdef.fog_start = 0;
6848                         r_refdef.fog_end = 0;
6849                         r_refdef.fog_height = 1<<30;
6850                         r_refdef.fog_fadedepth = 128;
6851                 }
6852         }
6853
6854         // fog parms
6855         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6856         r_refdef.fog_start = max(0, r_refdef.fog_start);
6857         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6858
6859         if (r_refdef.fog_density && r_drawfog.integer)
6860         {
6861                 r_refdef.fogenabled = true;
6862                 // this is the point where the fog reaches 0.9986 alpha, which we
6863                 // consider a good enough cutoff point for the texture
6864                 // (0.9986 * 256 == 255.6)
6865                 if (r_fog_exp2.integer)
6866                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6867                 else
6868                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6869                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6870                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6871                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6872                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6873                         R_BuildFogHeightTexture();
6874                 // fog color was already set
6875                 // update the fog texture
6876                 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)
6877                         R_BuildFogTexture();
6878                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6879                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6880         }
6881         else
6882                 r_refdef.fogenabled = false;
6883
6884         // fog color
6885         if (r_refdef.fog_density)
6886         {
6887                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6888                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6889                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6890
6891                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6892                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6893                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6894                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6895
6896                 {
6897                         vec3_t fogvec;
6898                         VectorCopy(r_refdef.fogcolor, fogvec);
6899                         //   color.rgb *= ContrastBoost * SceneBrightness;
6900                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6901                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6902                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6903                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6904                 }
6905         }
6906 }
6907
6908 void R_UpdateVariables(void)
6909 {
6910         R_Textures_Frame();
6911
6912         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6913
6914         r_refdef.farclip = r_farclip_base.value;
6915         if (r_refdef.scene.worldmodel)
6916                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6917         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6918
6919         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6920                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6921         r_refdef.polygonfactor = 0;
6922         r_refdef.polygonoffset = 0;
6923         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6924         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6925
6926         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6927         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6928         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6929         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6930         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6931         if (FAKELIGHT_ENABLED)
6932         {
6933                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6934         }
6935         else if (r_refdef.scene.worldmodel)
6936         {
6937                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6938         }
6939         if (r_showsurfaces.integer)
6940         {
6941                 r_refdef.scene.rtworld = false;
6942                 r_refdef.scene.rtworldshadows = false;
6943                 r_refdef.scene.rtdlight = false;
6944                 r_refdef.scene.rtdlightshadows = false;
6945                 r_refdef.scene.lightmapintensity = 0;
6946         }
6947
6948         r_gpuskeletal = false;
6949         switch(vid.renderpath)
6950         {
6951         case RENDERPATH_GL20:
6952                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6953         case RENDERPATH_D3D9:
6954         case RENDERPATH_D3D10:
6955         case RENDERPATH_D3D11:
6956         case RENDERPATH_SOFT:
6957         case RENDERPATH_GLES2:
6958                 if(!vid_gammatables_trivial)
6959                 {
6960                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6961                         {
6962                                 // build GLSL gamma texture
6963 #define RAMPWIDTH 256
6964                                 unsigned short ramp[RAMPWIDTH * 3];
6965                                 unsigned char rampbgr[RAMPWIDTH][4];
6966                                 int i;
6967
6968                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6969
6970                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6971                                 for(i = 0; i < RAMPWIDTH; ++i)
6972                                 {
6973                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6974                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6975                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6976                                         rampbgr[i][3] = 0;
6977                                 }
6978                                 if (r_texture_gammaramps)
6979                                 {
6980                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6981                                 }
6982                                 else
6983                                 {
6984                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6985                                 }
6986                         }
6987                 }
6988                 else
6989                 {
6990                         // remove GLSL gamma texture
6991                 }
6992                 break;
6993         case RENDERPATH_GL11:
6994         case RENDERPATH_GL13:
6995         case RENDERPATH_GLES1:
6996                 break;
6997         }
6998 }
6999
7000 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7001 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7002 /*
7003 ================
7004 R_SelectScene
7005 ================
7006 */
7007 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7008         if( scenetype != r_currentscenetype ) {
7009                 // store the old scenetype
7010                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7011                 r_currentscenetype = scenetype;
7012                 // move in the new scene
7013                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7014         }
7015 }
7016
7017 /*
7018 ================
7019 R_GetScenePointer
7020 ================
7021 */
7022 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7023 {
7024         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7025         if( scenetype == r_currentscenetype ) {
7026                 return &r_refdef.scene;
7027         } else {
7028                 return &r_scenes_store[ scenetype ];
7029         }
7030 }
7031
7032 static int R_SortEntities_Compare(const void *ap, const void *bp)
7033 {
7034         const entity_render_t *a = *(const entity_render_t **)ap;
7035         const entity_render_t *b = *(const entity_render_t **)bp;
7036
7037         // 1. compare model
7038         if(a->model < b->model)
7039                 return -1;
7040         if(a->model > b->model)
7041                 return +1;
7042
7043         // 2. compare skin
7044         // TODO possibly calculate the REAL skinnum here first using
7045         // skinscenes?
7046         if(a->skinnum < b->skinnum)
7047                 return -1;
7048         if(a->skinnum > b->skinnum)
7049                 return +1;
7050
7051         // everything we compared is equal
7052         return 0;
7053 }
7054 static void R_SortEntities(void)
7055 {
7056         // below or equal 2 ents, sorting never gains anything
7057         if(r_refdef.scene.numentities <= 2)
7058                 return;
7059         // sort
7060         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7061 }
7062
7063 /*
7064 ================
7065 R_RenderView
7066 ================
7067 */
7068 int dpsoftrast_test;
7069 extern cvar_t r_shadow_bouncegrid;
7070 void R_RenderView(void)
7071 {
7072         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7073         int fbo;
7074         rtexture_t *depthtexture;
7075         rtexture_t *colortexture;
7076
7077         dpsoftrast_test = r_test.integer;
7078
7079         if (r_timereport_active)
7080                 R_TimeReport("start");
7081         r_textureframe++; // used only by R_GetCurrentTexture
7082         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7083
7084         if(R_CompileShader_CheckStaticParms())
7085                 R_GLSL_Restart_f();
7086
7087         if (!r_drawentities.integer)
7088                 r_refdef.scene.numentities = 0;
7089         else if (r_sortentities.integer)
7090                 R_SortEntities();
7091
7092         R_AnimCache_ClearCache();
7093
7094         /* adjust for stereo display */
7095         if(R_Stereo_Active())
7096         {
7097                 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);
7098                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7099         }
7100
7101         if (r_refdef.view.isoverlay)
7102         {
7103                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7104                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7105                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7106                 R_TimeReport("depthclear");
7107
7108                 r_refdef.view.showdebug = false;
7109
7110                 r_fb.water.enabled = false;
7111                 r_fb.water.numwaterplanes = 0;
7112
7113                 R_RenderScene(0, NULL, NULL);
7114
7115                 r_refdef.view.matrix = originalmatrix;
7116
7117                 CHECKGLERROR
7118                 return;
7119         }
7120
7121         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7122         {
7123                 r_refdef.view.matrix = originalmatrix;
7124                 return;
7125         }
7126
7127         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7128
7129         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7130                 // in sRGB fallback, behave similar to true sRGB: convert this
7131                 // value from linear to sRGB
7132                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7133
7134         R_RenderView_UpdateViewVectors();
7135
7136         R_Shadow_UpdateWorldLightSelection();
7137
7138         R_Bloom_StartFrame();
7139
7140         // apply bloom brightness offset
7141         if(r_fb.bloomtexture[0])
7142                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7143
7144         R_Water_StartFrame();
7145
7146         // now we probably have an fbo to render into
7147         fbo = r_fb.fbo;
7148         depthtexture = r_fb.depthtexture;
7149         colortexture = r_fb.colortexture;
7150
7151         CHECKGLERROR
7152         if (r_timereport_active)
7153                 R_TimeReport("viewsetup");
7154
7155         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7156
7157         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7158         {
7159                 R_ClearScreen(r_refdef.fogenabled);
7160                 if (r_timereport_active)
7161                         R_TimeReport("viewclear");
7162         }
7163         r_refdef.view.clear = true;
7164
7165         r_refdef.view.showdebug = true;
7166
7167         R_View_Update();
7168         if (r_timereport_active)
7169                 R_TimeReport("visibility");
7170
7171         R_AnimCache_CacheVisibleEntities();
7172         if (r_timereport_active)
7173                 R_TimeReport("animcache");
7174
7175         R_Shadow_UpdateBounceGridTexture();
7176         if (r_timereport_active && r_shadow_bouncegrid.integer)
7177                 R_TimeReport("bouncegrid");
7178
7179         r_fb.water.numwaterplanes = 0;
7180         if (r_fb.water.enabled)
7181                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7182
7183         R_RenderScene(fbo, depthtexture, colortexture);
7184         r_fb.water.numwaterplanes = 0;
7185
7186         R_BlendView(fbo, depthtexture, colortexture);
7187         if (r_timereport_active)
7188                 R_TimeReport("blendview");
7189
7190         GL_Scissor(0, 0, vid.width, vid.height);
7191         GL_ScissorTest(false);
7192
7193         r_refdef.view.matrix = originalmatrix;
7194
7195         CHECKGLERROR
7196 }
7197
7198 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7199 {
7200         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7201         {
7202                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7203                 if (r_timereport_active)
7204                         R_TimeReport("waterworld");
7205         }
7206
7207         // don't let sound skip if going slow
7208         if (r_refdef.scene.extraupdate)
7209                 S_ExtraUpdate ();
7210
7211         R_DrawModelsAddWaterPlanes();
7212         if (r_timereport_active)
7213                 R_TimeReport("watermodels");
7214
7215         if (r_fb.water.numwaterplanes)
7216         {
7217                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7218                 if (r_timereport_active)
7219                         R_TimeReport("waterscenes");
7220         }
7221 }
7222
7223 extern cvar_t cl_locs_show;
7224 static void R_DrawLocs(void);
7225 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7226 static void R_DrawModelDecals(void);
7227 extern cvar_t cl_decals_newsystem;
7228 extern qboolean r_shadow_usingdeferredprepass;
7229 extern int r_shadow_shadowmapatlas_modelshadows_size;
7230 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7231 {
7232         qboolean shadowmapping = false;
7233
7234         if (r_timereport_active)
7235                 R_TimeReport("beginscene");
7236
7237         r_refdef.stats[r_stat_renders]++;
7238
7239         R_UpdateFog();
7240
7241         // don't let sound skip if going slow
7242         if (r_refdef.scene.extraupdate)
7243                 S_ExtraUpdate ();
7244
7245         R_MeshQueue_BeginScene();
7246
7247         R_SkyStartFrame();
7248
7249         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);
7250
7251         if (r_timereport_active)
7252                 R_TimeReport("skystartframe");
7253
7254         if (cl.csqc_vidvars.drawworld)
7255         {
7256                 // don't let sound skip if going slow
7257                 if (r_refdef.scene.extraupdate)
7258                         S_ExtraUpdate ();
7259
7260                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7261                 {
7262                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7263                         if (r_timereport_active)
7264                                 R_TimeReport("worldsky");
7265                 }
7266
7267                 if (R_DrawBrushModelsSky() && r_timereport_active)
7268                         R_TimeReport("bmodelsky");
7269
7270                 if (skyrendermasked && skyrenderlater)
7271                 {
7272                         // we have to force off the water clipping plane while rendering sky
7273                         R_SetupView(false, fbo, depthtexture, colortexture);
7274                         R_Sky();
7275                         R_SetupView(true, fbo, depthtexture, colortexture);
7276                         if (r_timereport_active)
7277                                 R_TimeReport("sky");
7278                 }
7279         }
7280
7281         R_Shadow_PrepareModelShadows();
7282         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7283         if (r_timereport_active)
7284                 R_TimeReport("preparelights");
7285
7286         // render all the shadowmaps that will be used for this view
7287         shadowmapping = R_Shadow_ShadowMappingEnabled();
7288         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7289         {
7290                 R_Shadow_DrawShadowMaps();
7291                 if (r_timereport_active)
7292                         R_TimeReport("shadowmaps");
7293         }
7294
7295         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7296         if (r_shadow_usingdeferredprepass)
7297                 R_Shadow_DrawPrepass();
7298
7299         // now we begin the forward pass of the view render
7300         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7301         {
7302                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7303                 if (r_timereport_active)
7304                         R_TimeReport("worlddepth");
7305         }
7306         if (r_depthfirst.integer >= 2)
7307         {
7308                 R_DrawModelsDepth();
7309                 if (r_timereport_active)
7310                         R_TimeReport("modeldepth");
7311         }
7312
7313         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7314         {
7315                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7316                 if (r_timereport_active)
7317                         R_TimeReport("world");
7318         }
7319
7320         // don't let sound skip if going slow
7321         if (r_refdef.scene.extraupdate)
7322                 S_ExtraUpdate ();
7323
7324         R_DrawModels();
7325         if (r_timereport_active)
7326                 R_TimeReport("models");
7327
7328         // don't let sound skip if going slow
7329         if (r_refdef.scene.extraupdate)
7330                 S_ExtraUpdate ();
7331
7332         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7333         {
7334                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7335                 R_Shadow_DrawModelShadows();
7336                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7337                 // don't let sound skip if going slow
7338                 if (r_refdef.scene.extraupdate)
7339                         S_ExtraUpdate ();
7340         }
7341
7342         if (!r_shadow_usingdeferredprepass)
7343         {
7344                 R_Shadow_DrawLights();
7345                 if (r_timereport_active)
7346                         R_TimeReport("rtlights");
7347         }
7348
7349         // don't let sound skip if going slow
7350         if (r_refdef.scene.extraupdate)
7351                 S_ExtraUpdate ();
7352
7353         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7354         {
7355                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7356                 R_Shadow_DrawModelShadows();
7357                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7358                 // don't let sound skip if going slow
7359                 if (r_refdef.scene.extraupdate)
7360                         S_ExtraUpdate ();
7361         }
7362
7363         if (cl.csqc_vidvars.drawworld)
7364         {
7365                 if (cl_decals_newsystem.integer)
7366                 {
7367                         R_DrawModelDecals();
7368                         if (r_timereport_active)
7369                                 R_TimeReport("modeldecals");
7370                 }
7371                 else
7372                 {
7373                         R_DrawDecals();
7374                         if (r_timereport_active)
7375                                 R_TimeReport("decals");
7376                 }
7377
7378                 R_DrawParticles();
7379                 if (r_timereport_active)
7380                         R_TimeReport("particles");
7381
7382                 R_DrawExplosions();
7383                 if (r_timereport_active)
7384                         R_TimeReport("explosions");
7385         }
7386
7387         if (cl.csqc_loaded)
7388                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7389
7390         if (r_refdef.view.showdebug)
7391         {
7392                 if (cl_locs_show.integer)
7393                 {
7394                         R_DrawLocs();
7395                         if (r_timereport_active)
7396                                 R_TimeReport("showlocs");
7397                 }
7398
7399                 if (r_drawportals.integer)
7400                 {
7401                         R_DrawPortals();
7402                         if (r_timereport_active)
7403                                 R_TimeReport("portals");
7404                 }
7405
7406                 if (r_showbboxes_client.value > 0)
7407                 {
7408                         R_DrawEntityBBoxes(CLVM_prog);
7409                         if (r_timereport_active)
7410                                 R_TimeReport("clbboxes");
7411                 }
7412                 if (r_showbboxes.value > 0)
7413                 {
7414                         R_DrawEntityBBoxes(SVVM_prog);
7415                         if (r_timereport_active)
7416                                 R_TimeReport("svbboxes");
7417                 }
7418         }
7419
7420         if (r_transparent.integer)
7421         {
7422                 R_MeshQueue_RenderTransparent();
7423                 if (r_timereport_active)
7424                         R_TimeReport("drawtrans");
7425         }
7426
7427         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))
7428         {
7429                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7430                 if (r_timereport_active)
7431                         R_TimeReport("worlddebug");
7432                 R_DrawModelsDebug();
7433                 if (r_timereport_active)
7434                         R_TimeReport("modeldebug");
7435         }
7436
7437         if (cl.csqc_vidvars.drawworld)
7438         {
7439                 R_Shadow_DrawCoronas();
7440                 if (r_timereport_active)
7441                         R_TimeReport("coronas");
7442         }
7443
7444 #if 0
7445         {
7446                 GL_DepthTest(false);
7447                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7448                 GL_Color(1, 1, 1, 1);
7449                 qglBegin(GL_POLYGON);
7450                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7451                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7452                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7453                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7454                 qglEnd();
7455                 qglBegin(GL_POLYGON);
7456                 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]);
7457                 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]);
7458                 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]);
7459                 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]);
7460                 qglEnd();
7461                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7462         }
7463 #endif
7464
7465         // don't let sound skip if going slow
7466         if (r_refdef.scene.extraupdate)
7467                 S_ExtraUpdate ();
7468 }
7469
7470 static const unsigned short bboxelements[36] =
7471 {
7472         5, 1, 3, 5, 3, 7,
7473         6, 2, 0, 6, 0, 4,
7474         7, 3, 2, 7, 2, 6,
7475         4, 0, 1, 4, 1, 5,
7476         4, 5, 7, 4, 7, 6,
7477         1, 0, 2, 1, 2, 3,
7478 };
7479
7480 #define BBOXEDGES 13
7481 static const float bboxedges[BBOXEDGES][6] = 
7482 {
7483         // whole box
7484         { 0, 0, 0, 1, 1, 1 },
7485         // bottom edges
7486         { 0, 0, 0, 0, 1, 0 },
7487         { 0, 0, 0, 1, 0, 0 },
7488         { 0, 1, 0, 1, 1, 0 },
7489         { 1, 0, 0, 1, 1, 0 },
7490         // top edges
7491         { 0, 0, 1, 0, 1, 1 },
7492         { 0, 0, 1, 1, 0, 1 },
7493         { 0, 1, 1, 1, 1, 1 },
7494         { 1, 0, 1, 1, 1, 1 },
7495         // vertical edges
7496         { 0, 0, 0, 0, 0, 1 },
7497         { 1, 0, 0, 1, 0, 1 },
7498         { 0, 1, 0, 0, 1, 1 },
7499         { 1, 1, 0, 1, 1, 1 },
7500 };
7501
7502 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7503 {
7504         int numvertices = BBOXEDGES * 8;
7505         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7506         int numtriangles = BBOXEDGES * 12;
7507         unsigned short elements[BBOXEDGES * 36];
7508         int i, edge;
7509         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7510
7511         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7512
7513         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7514         GL_DepthMask(false);
7515         GL_DepthRange(0, 1);
7516         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7517
7518         for (edge = 0; edge < BBOXEDGES; edge++)
7519         {
7520                 for (i = 0; i < 3; i++)
7521                 {
7522                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7523                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7524                 }
7525                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7526                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7527                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7528                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7529                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7530                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7531                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7532                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7533                 for (i = 0; i < 36; i++)
7534                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7535         }
7536         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7537         if (r_refdef.fogenabled)
7538         {
7539                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7540                 {
7541                         f1 = RSurf_FogVertex(v);
7542                         f2 = 1 - f1;
7543                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7544                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7545                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7546                 }
7547         }
7548         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7549         R_Mesh_ResetTextureState();
7550         R_SetupShader_Generic_NoTexture(false, false);
7551         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7552 }
7553
7554 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7555 {
7556         // hacky overloading of the parameters
7557         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7558         int i;
7559         float color[4];
7560         prvm_edict_t *edict;
7561
7562         GL_CullFace(GL_NONE);
7563         R_SetupShader_Generic_NoTexture(false, false);
7564
7565         for (i = 0;i < numsurfaces;i++)
7566         {
7567                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7568                 switch ((int)PRVM_serveredictfloat(edict, solid))
7569                 {
7570                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7571                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7572                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7573                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7574                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7575                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7576                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7577                 }
7578                 if (prog == CLVM_prog)
7579                         color[3] *= r_showbboxes_client.value;
7580                 else
7581                         color[3] *= r_showbboxes.value;
7582                 color[3] = bound(0, color[3], 1);
7583                 GL_DepthTest(!r_showdisabledepthtest.integer);
7584                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7585         }
7586 }
7587
7588 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7589 {
7590         int i;
7591         prvm_edict_t *edict;
7592         vec3_t center;
7593
7594         if (prog == NULL)
7595                 return;
7596
7597         for (i = 0; i < prog->num_edicts; i++)
7598         {
7599                 edict = PRVM_EDICT_NUM(i);
7600                 if (edict->priv.server->free)
7601                         continue;
7602                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7603                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7604                         continue;
7605                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7606                         continue;
7607                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7608                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7609         }
7610 }
7611
7612 static const int nomodelelement3i[24] =
7613 {
7614         5, 2, 0,
7615         5, 1, 2,
7616         5, 0, 3,
7617         5, 3, 1,
7618         0, 2, 4,
7619         2, 1, 4,
7620         3, 0, 4,
7621         1, 3, 4
7622 };
7623
7624 static const unsigned short nomodelelement3s[24] =
7625 {
7626         5, 2, 0,
7627         5, 1, 2,
7628         5, 0, 3,
7629         5, 3, 1,
7630         0, 2, 4,
7631         2, 1, 4,
7632         3, 0, 4,
7633         1, 3, 4
7634 };
7635
7636 static const float nomodelvertex3f[6*3] =
7637 {
7638         -16,   0,   0,
7639          16,   0,   0,
7640           0, -16,   0,
7641           0,  16,   0,
7642           0,   0, -16,
7643           0,   0,  16
7644 };
7645
7646 static const float nomodelcolor4f[6*4] =
7647 {
7648         0.0f, 0.0f, 0.5f, 1.0f,
7649         0.0f, 0.0f, 0.5f, 1.0f,
7650         0.0f, 0.5f, 0.0f, 1.0f,
7651         0.0f, 0.5f, 0.0f, 1.0f,
7652         0.5f, 0.0f, 0.0f, 1.0f,
7653         0.5f, 0.0f, 0.0f, 1.0f
7654 };
7655
7656 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7657 {
7658         int i;
7659         float f1, f2, *c;
7660         float color4f[6*4];
7661
7662         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);
7663
7664         // this is only called once per entity so numsurfaces is always 1, and
7665         // surfacelist is always {0}, so this code does not handle batches
7666
7667         if (rsurface.ent_flags & RENDER_ADDITIVE)
7668         {
7669                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7670                 GL_DepthMask(false);
7671         }
7672         else if (ent->alpha < 1)
7673         {
7674                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7675                 GL_DepthMask(false);
7676         }
7677         else
7678         {
7679                 GL_BlendFunc(GL_ONE, GL_ZERO);
7680                 GL_DepthMask(true);
7681         }
7682         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7683         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7684         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7685         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7686         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7687         for (i = 0, c = color4f;i < 6;i++, c += 4)
7688         {
7689                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7690                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7691                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7692                 c[3] *= ent->alpha;
7693         }
7694         if (r_refdef.fogenabled)
7695         {
7696                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7697                 {
7698                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7699                         f2 = 1 - f1;
7700                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7701                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7702                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7703                 }
7704         }
7705 //      R_Mesh_ResetTextureState();
7706         R_SetupShader_Generic_NoTexture(false, false);
7707         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7708         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7709 }
7710
7711 void R_DrawNoModel(entity_render_t *ent)
7712 {
7713         vec3_t org;
7714         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7715         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7716                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7717         else
7718                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7719 }
7720
7721 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7722 {
7723         vec3_t right1, right2, diff, normal;
7724
7725         VectorSubtract (org2, org1, normal);
7726
7727         // calculate 'right' vector for start
7728         VectorSubtract (r_refdef.view.origin, org1, diff);
7729         CrossProduct (normal, diff, right1);
7730         VectorNormalize (right1);
7731
7732         // calculate 'right' vector for end
7733         VectorSubtract (r_refdef.view.origin, org2, diff);
7734         CrossProduct (normal, diff, right2);
7735         VectorNormalize (right2);
7736
7737         vert[ 0] = org1[0] + width * right1[0];
7738         vert[ 1] = org1[1] + width * right1[1];
7739         vert[ 2] = org1[2] + width * right1[2];
7740         vert[ 3] = org1[0] - width * right1[0];
7741         vert[ 4] = org1[1] - width * right1[1];
7742         vert[ 5] = org1[2] - width * right1[2];
7743         vert[ 6] = org2[0] - width * right2[0];
7744         vert[ 7] = org2[1] - width * right2[1];
7745         vert[ 8] = org2[2] - width * right2[2];
7746         vert[ 9] = org2[0] + width * right2[0];
7747         vert[10] = org2[1] + width * right2[1];
7748         vert[11] = org2[2] + width * right2[2];
7749 }
7750
7751 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)
7752 {
7753         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7754         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7755         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7756         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7757         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7758         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7759         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7760         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7761         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7762         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7763         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7764         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7765 }
7766
7767 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7768 {
7769         int i;
7770         float *vertex3f;
7771         float v[3];
7772         VectorSet(v, x, y, z);
7773         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7774                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7775                         break;
7776         if (i == mesh->numvertices)
7777         {
7778                 if (mesh->numvertices < mesh->maxvertices)
7779                 {
7780                         VectorCopy(v, vertex3f);
7781                         mesh->numvertices++;
7782                 }
7783                 return mesh->numvertices;
7784         }
7785         else
7786                 return i;
7787 }
7788
7789 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7790 {
7791         int i;
7792         int *e, element[3];
7793         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7794         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7795         e = mesh->element3i + mesh->numtriangles * 3;
7796         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7797         {
7798                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7799                 if (mesh->numtriangles < mesh->maxtriangles)
7800                 {
7801                         *e++ = element[0];
7802                         *e++ = element[1];
7803                         *e++ = element[2];
7804                         mesh->numtriangles++;
7805                 }
7806                 element[1] = element[2];
7807         }
7808 }
7809
7810 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7811 {
7812         int i;
7813         int *e, element[3];
7814         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7815         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7816         e = mesh->element3i + mesh->numtriangles * 3;
7817         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7818         {
7819                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7820                 if (mesh->numtriangles < mesh->maxtriangles)
7821                 {
7822                         *e++ = element[0];
7823                         *e++ = element[1];
7824                         *e++ = element[2];
7825                         mesh->numtriangles++;
7826                 }
7827                 element[1] = element[2];
7828         }
7829 }
7830
7831 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7832 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7833 {
7834         int planenum, planenum2;
7835         int w;
7836         int tempnumpoints;
7837         mplane_t *plane, *plane2;
7838         double maxdist;
7839         double temppoints[2][256*3];
7840         // figure out how large a bounding box we need to properly compute this brush
7841         maxdist = 0;
7842         for (w = 0;w < numplanes;w++)
7843                 maxdist = max(maxdist, fabs(planes[w].dist));
7844         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7845         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7846         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7847         {
7848                 w = 0;
7849                 tempnumpoints = 4;
7850                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7851                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7852                 {
7853                         if (planenum2 == planenum)
7854                                 continue;
7855                         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);
7856                         w = !w;
7857                 }
7858                 if (tempnumpoints < 3)
7859                         continue;
7860                 // generate elements forming a triangle fan for this polygon
7861                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7862         }
7863 }
7864
7865 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)
7866 {
7867         texturelayer_t *layer;
7868         layer = t->currentlayers + t->currentnumlayers++;
7869         layer->type = type;
7870         layer->depthmask = depthmask;
7871         layer->blendfunc1 = blendfunc1;
7872         layer->blendfunc2 = blendfunc2;
7873         layer->texture = texture;
7874         layer->texmatrix = *matrix;
7875         layer->color[0] = r;
7876         layer->color[1] = g;
7877         layer->color[2] = b;
7878         layer->color[3] = a;
7879 }
7880
7881 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7882 {
7883         if(parms[0] == 0 && parms[1] == 0)
7884                 return false;
7885         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7886                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7887                         return false;
7888         return true;
7889 }
7890
7891 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7892 {
7893         double index, f;
7894         index = parms[2] + rsurface.shadertime * parms[3];
7895         index -= floor(index);
7896         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7897         {
7898         default:
7899         case Q3WAVEFUNC_NONE:
7900         case Q3WAVEFUNC_NOISE:
7901         case Q3WAVEFUNC_COUNT:
7902                 f = 0;
7903                 break;
7904         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7905         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7906         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7907         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7908         case Q3WAVEFUNC_TRIANGLE:
7909                 index *= 4;
7910                 f = index - floor(index);
7911                 if (index < 1)
7912                 {
7913                         // f = f;
7914                 }
7915                 else if (index < 2)
7916                         f = 1 - f;
7917                 else if (index < 3)
7918                         f = -f;
7919                 else
7920                         f = -(1 - f);
7921                 break;
7922         }
7923         f = parms[0] + parms[1] * f;
7924         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7925                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7926         return (float) f;
7927 }
7928
7929 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7930 {
7931         int w, h, idx;
7932         float shadertime;
7933         float f;
7934         float offsetd[2];
7935         float tcmat[12];
7936         matrix4x4_t matrix, temp;
7937         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7938         // it's better to have one huge fixup every 9 hours than gradual
7939         // degradation over time which looks consistently bad after many hours.
7940         //
7941         // tcmod scroll in particular suffers from this degradation which can't be
7942         // effectively worked around even with floor() tricks because we don't
7943         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7944         // a workaround involving floor() would be incorrect anyway...
7945         shadertime = rsurface.shadertime;
7946         if (shadertime >= 32768.0f)
7947                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7948         switch(tcmod->tcmod)
7949         {
7950                 case Q3TCMOD_COUNT:
7951                 case Q3TCMOD_NONE:
7952                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7953                                 matrix = r_waterscrollmatrix;
7954                         else
7955                                 matrix = identitymatrix;
7956                         break;
7957                 case Q3TCMOD_ENTITYTRANSLATE:
7958                         // this is used in Q3 to allow the gamecode to control texcoord
7959                         // scrolling on the entity, which is not supported in darkplaces yet.
7960                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7961                         break;
7962                 case Q3TCMOD_ROTATE:
7963                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7964                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7965                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7966                         break;
7967                 case Q3TCMOD_SCALE:
7968                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7969                         break;
7970                 case Q3TCMOD_SCROLL:
7971                         // this particular tcmod is a "bug for bug" compatible one with regards to
7972                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7973                         // specifically did the wrapping and so we must mimic that...
7974                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7975                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7976                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7977                         break;
7978                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7979                         w = (int) tcmod->parms[0];
7980                         h = (int) tcmod->parms[1];
7981                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7982                         f = f - floor(f);
7983                         idx = (int) floor(f * w * h);
7984                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7985                         break;
7986                 case Q3TCMOD_STRETCH:
7987                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7988                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7989                         break;
7990                 case Q3TCMOD_TRANSFORM:
7991                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7992                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7993                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7994                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7995                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7996                         break;
7997                 case Q3TCMOD_TURBULENT:
7998                         // this is handled in the RSurf_PrepareVertices function
7999                         matrix = identitymatrix;
8000                         break;
8001         }
8002         temp = *texmatrix;
8003         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8004 }
8005
8006 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8007 {
8008         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8009         char name[MAX_QPATH];
8010         skinframe_t *skinframe;
8011         unsigned char pixels[296*194];
8012         strlcpy(cache->name, skinname, sizeof(cache->name));
8013         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8014         if (developer_loading.integer)
8015                 Con_Printf("loading %s\n", name);
8016         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8017         if (!skinframe || !skinframe->base)
8018         {
8019                 unsigned char *f;
8020                 fs_offset_t filesize;
8021                 skinframe = NULL;
8022                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8023                 if (f)
8024                 {
8025                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8026                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8027                         Mem_Free(f);
8028                 }
8029         }
8030         cache->skinframe = skinframe;
8031 }
8032
8033 texture_t *R_GetCurrentTexture(texture_t *t)
8034 {
8035         int i, q;
8036         const entity_render_t *ent = rsurface.entity;
8037         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8038         q3shaderinfo_layer_tcmod_t *tcmod;
8039         float specularscale = 0.0f;
8040
8041         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8042                 return t->currentframe;
8043         t->update_lastrenderframe = r_textureframe;
8044         t->update_lastrenderentity = (void *)ent;
8045
8046         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8047                 t->camera_entity = ent->entitynumber;
8048         else
8049                 t->camera_entity = 0;
8050
8051         // switch to an alternate material if this is a q1bsp animated material
8052         {
8053                 texture_t *texture = t;
8054                 int s = rsurface.ent_skinnum;
8055                 if ((unsigned int)s >= (unsigned int)model->numskins)
8056                         s = 0;
8057                 if (model->skinscenes)
8058                 {
8059                         if (model->skinscenes[s].framecount > 1)
8060                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8061                         else
8062                                 s = model->skinscenes[s].firstframe;
8063                 }
8064                 if (s > 0)
8065                         t = t + s * model->num_surfaces;
8066                 if (t->animated)
8067                 {
8068                         // use an alternate animation if the entity's frame is not 0,
8069                         // and only if the texture has an alternate animation
8070                         if (t->animated == 2) // q2bsp
8071                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8072                         else if (rsurface.ent_alttextures && t->anim_total[1])
8073                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8074                         else
8075                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8076                 }
8077                 texture->currentframe = t;
8078         }
8079
8080         // update currentskinframe to be a qw skin or animation frame
8081         if (rsurface.ent_qwskin >= 0)
8082         {
8083                 i = rsurface.ent_qwskin;
8084                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8085                 {
8086                         r_qwskincache_size = cl.maxclients;
8087                         if (r_qwskincache)
8088                                 Mem_Free(r_qwskincache);
8089                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8090                 }
8091                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8092                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8093                 t->currentskinframe = r_qwskincache[i].skinframe;
8094                 if (t->materialshaderpass && t->currentskinframe == NULL)
8095                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8096         }
8097         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8098                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8099         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8100                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8101
8102         t->currentmaterialflags = t->basematerialflags;
8103         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8104         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8105                 t->currentalpha *= r_wateralpha.value;
8106         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8107                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8108         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8109                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8110
8111         // decide on which type of lighting to use for this surface
8112         if (rsurface.entity->render_modellight_forced)
8113                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8114         if (rsurface.entity->render_rtlight_disabled)
8115                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8116         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8117         {
8118                 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8119                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8120                 for (q = 0; q < 3; q++)
8121                 {
8122                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8123                         t->render_modellight_lightdir[q] = q == 2;
8124                         t->render_modellight_ambient[q] = 1;
8125                         t->render_modellight_diffuse[q] = 0;
8126                         t->render_modellight_specular[q] = 0;
8127                         t->render_lightmap_ambient[q] = 0;
8128                         t->render_lightmap_diffuse[q] = 0;
8129                         t->render_lightmap_specular[q] = 0;
8130                         t->render_rtlight_diffuse[q] = 0;
8131                         t->render_rtlight_specular[q] = 0;
8132                 }
8133         }
8134         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8135         {
8136                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8137                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8138                 for (q = 0; q < 3; q++)
8139                 {
8140                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8141                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8142                         t->render_modellight_lightdir[q] = q == 2;
8143                         t->render_modellight_diffuse[q] = 0;
8144                         t->render_modellight_specular[q] = 0;
8145                         t->render_lightmap_ambient[q] = 0;
8146                         t->render_lightmap_diffuse[q] = 0;
8147                         t->render_lightmap_specular[q] = 0;
8148                         t->render_rtlight_diffuse[q] = 0;
8149                         t->render_rtlight_specular[q] = 0;
8150                 }
8151         }
8152         else if (FAKELIGHT_ENABLED)
8153         {
8154                 // no modellight if using fakelight for the map
8155                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8156                 for (q = 0; q < 3; q++)
8157                 {
8158                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8159                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8160                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8161                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8162                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8163                         t->render_lightmap_ambient[q] = 0;
8164                         t->render_lightmap_diffuse[q] = 0;
8165                         t->render_lightmap_specular[q] = 0;
8166                         t->render_rtlight_diffuse[q] = 0;
8167                         t->render_rtlight_specular[q] = 0;
8168                 }
8169         }
8170         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8171         {
8172                 // ambient + single direction light (modellight)
8173                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8174                 for (q = 0; q < 3; q++)
8175                 {
8176                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8177                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8178                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8179                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8180                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8181                         t->render_lightmap_ambient[q] = 0;
8182                         t->render_lightmap_diffuse[q] = 0;
8183                         t->render_lightmap_specular[q] = 0;
8184                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8185                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8186                 }
8187         }
8188         else
8189         {
8190                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8191                 for (q = 0; q < 3; q++)
8192                 {
8193                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8194                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8195                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8196                         t->render_modellight_diffuse[q] = 0;
8197                         t->render_modellight_specular[q] = 0;
8198                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8199                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8200                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8201                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8202                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8203                 }
8204         }
8205
8206         for (q = 0; q < 3; q++)
8207         {
8208                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8209                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8210         }
8211
8212         if (rsurface.ent_flags & RENDER_ADDITIVE)
8213                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8214         else if (t->currentalpha < 1)
8215                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8216         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8217         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8218                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8219         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8220                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8221         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8222                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8223         if (t->backgroundshaderpass)
8224                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8225         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8226         {
8227                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8228                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8229         }
8230         else
8231                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8232         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8233         {
8234                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8235                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8236         }
8237         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8238                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8239
8240         // there is no tcmod
8241         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8242         {
8243                 t->currenttexmatrix = r_waterscrollmatrix;
8244                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8245         }
8246         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8247         {
8248                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8249                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8250         }
8251
8252         if (t->materialshaderpass)
8253                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8254                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8255
8256         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8257         if (t->currentskinframe->qpixels)
8258                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8259         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8260         if (!t->basetexture)
8261                 t->basetexture = r_texture_notexture;
8262         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8263         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8264         t->nmaptexture = t->currentskinframe->nmap;
8265         if (!t->nmaptexture)
8266                 t->nmaptexture = r_texture_blanknormalmap;
8267         t->glosstexture = r_texture_black;
8268         t->glowtexture = t->currentskinframe->glow;
8269         t->fogtexture = t->currentskinframe->fog;
8270         t->reflectmasktexture = t->currentskinframe->reflect;
8271         if (t->backgroundshaderpass)
8272         {
8273                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8274                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8275                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8276                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8277                 t->backgroundglosstexture = r_texture_black;
8278                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8279                 if (!t->backgroundnmaptexture)
8280                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8281                 // make sure that if glow is going to be used, both textures are not NULL
8282                 if (!t->backgroundglowtexture && t->glowtexture)
8283                         t->backgroundglowtexture = r_texture_black;
8284                 if (!t->glowtexture && t->backgroundglowtexture)
8285                         t->glowtexture = r_texture_black;
8286         }
8287         else
8288         {
8289                 t->backgroundbasetexture = r_texture_white;
8290                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8291                 t->backgroundglosstexture = r_texture_black;
8292                 t->backgroundglowtexture = NULL;
8293         }
8294         t->specularpower = r_shadow_glossexponent.value;
8295         // TODO: store reference values for these in the texture?
8296         if (r_shadow_gloss.integer > 0)
8297         {
8298                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8299                 {
8300                         if (r_shadow_glossintensity.value > 0)
8301                         {
8302                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8303                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8304                                 specularscale = r_shadow_glossintensity.value;
8305                         }
8306                 }
8307                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8308                 {
8309                         t->glosstexture = r_texture_white;
8310                         t->backgroundglosstexture = r_texture_white;
8311                         specularscale = r_shadow_gloss2intensity.value;
8312                         t->specularpower = r_shadow_gloss2exponent.value;
8313                 }
8314         }
8315         specularscale *= t->specularscalemod;
8316         t->specularpower *= t->specularpowermod;
8317
8318         // lightmaps mode looks bad with dlights using actual texturing, so turn
8319         // off the colormap and glossmap, but leave the normalmap on as it still
8320         // accurately represents the shading involved
8321         if (gl_lightmaps.integer)
8322         {
8323                 t->basetexture = r_texture_grey128;
8324                 t->pantstexture = r_texture_black;
8325                 t->shirttexture = r_texture_black;
8326                 if (gl_lightmaps.integer < 2)
8327                         t->nmaptexture = r_texture_blanknormalmap;
8328                 t->glosstexture = r_texture_black;
8329                 t->glowtexture = NULL;
8330                 t->fogtexture = NULL;
8331                 t->reflectmasktexture = NULL;
8332                 t->backgroundbasetexture = NULL;
8333                 if (gl_lightmaps.integer < 2)
8334                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8335                 t->backgroundglosstexture = r_texture_black;
8336                 t->backgroundglowtexture = NULL;
8337                 specularscale = 0;
8338                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8339         }
8340
8341         if (specularscale != 1.0f)
8342         {
8343                 for (q = 0; q < 3; q++)
8344                 {
8345                         t->render_modellight_specular[q] *= specularscale;
8346                         t->render_lightmap_specular[q] *= specularscale;
8347                         t->render_rtlight_specular[q] *= specularscale;
8348                 }
8349         }
8350
8351         t->currentnumlayers = 0;
8352         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8353         {
8354                 int blendfunc1, blendfunc2;
8355                 qboolean depthmask;
8356                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8357                 {
8358                         blendfunc1 = GL_SRC_ALPHA;
8359                         blendfunc2 = GL_ONE;
8360                 }
8361                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8362                 {
8363                         blendfunc1 = GL_SRC_ALPHA;
8364                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8365                 }
8366                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8367                 {
8368                         blendfunc1 = t->customblendfunc[0];
8369                         blendfunc2 = t->customblendfunc[1];
8370                 }
8371                 else
8372                 {
8373                         blendfunc1 = GL_ONE;
8374                         blendfunc2 = GL_ZERO;
8375                 }
8376                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8377                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8378                 {
8379                         // basic lit geometry
8380                         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);
8381                         // add pants/shirt if needed
8382                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8383                                 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);
8384                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8385                                 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);
8386                 }
8387                 else
8388                 {
8389                         // basic lit geometry
8390                         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);
8391                         // add pants/shirt if needed
8392                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8393                                 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);
8394                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8395                                 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);
8396                         // now add ambient passes if needed
8397                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8398                         {
8399                                 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);
8400                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8401                                         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);
8402                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8403                                         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);
8404                         }
8405                 }
8406                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8407                         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);
8408                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8409                 {
8410                         // if this is opaque use alpha blend which will darken the earlier
8411                         // passes cheaply.
8412                         //
8413                         // if this is an alpha blended material, all the earlier passes
8414                         // were darkened by fog already, so we only need to add the fog
8415                         // color ontop through the fog mask texture
8416                         //
8417                         // if this is an additive blended material, all the earlier passes
8418                         // were darkened by fog already, and we should not add fog color
8419                         // (because the background was not darkened, there is no fog color
8420                         // that was lost behind it).
8421                         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);
8422                 }
8423         }
8424
8425         return t;
8426 }
8427
8428 rsurfacestate_t rsurface;
8429
8430 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8431 {
8432         dp_model_t *model = ent->model;
8433         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8434         //      return;
8435         rsurface.entity = (entity_render_t *)ent;
8436         rsurface.skeleton = ent->skeleton;
8437         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8438         rsurface.ent_skinnum = ent->skinnum;
8439         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;
8440         rsurface.ent_flags = ent->flags;
8441         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8442                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8443         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8444         rsurface.matrix = ent->matrix;
8445         rsurface.inversematrix = ent->inversematrix;
8446         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8447         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8448         R_EntityMatrix(&rsurface.matrix);
8449         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8450         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8451         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8452         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8453         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8454         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8455         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8456         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8457         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8458         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8459         if (ent->model->brush.submodel && !prepass)
8460         {
8461                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8462                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8463         }
8464         // if the animcache code decided it should use the shader path, skip the deform step
8465         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8466         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8467         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8468         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8469         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8470         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8471         {
8472                 if (ent->animcache_vertex3f)
8473                 {
8474                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8475                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8476                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8477                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8478                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8479                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8480                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8481                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8482                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8483                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8484                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8485                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8486                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8487                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8488                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8489                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8490                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8491                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8492                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8493                 }
8494                 else if (wanttangents)
8495                 {
8496                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8497                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8498                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8499                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8500                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8501                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8502                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8503                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8504                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8505                         rsurface.modelvertexmesh = NULL;
8506                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8507                         rsurface.modelvertexmesh_bufferoffset = 0;
8508                         rsurface.modelvertex3f_vertexbuffer = NULL;
8509                         rsurface.modelvertex3f_bufferoffset = 0;
8510                         rsurface.modelvertex3f_vertexbuffer = 0;
8511                         rsurface.modelvertex3f_bufferoffset = 0;
8512                         rsurface.modelsvector3f_vertexbuffer = 0;
8513                         rsurface.modelsvector3f_bufferoffset = 0;
8514                         rsurface.modeltvector3f_vertexbuffer = 0;
8515                         rsurface.modeltvector3f_bufferoffset = 0;
8516                         rsurface.modelnormal3f_vertexbuffer = 0;
8517                         rsurface.modelnormal3f_bufferoffset = 0;
8518                 }
8519                 else if (wantnormals)
8520                 {
8521                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8522                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8523                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8524                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8525                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8526                         rsurface.modelsvector3f = NULL;
8527                         rsurface.modeltvector3f = NULL;
8528                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8529                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8530                         rsurface.modelvertexmesh = NULL;
8531                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8532                         rsurface.modelvertexmesh_bufferoffset = 0;
8533                         rsurface.modelvertex3f_vertexbuffer = NULL;
8534                         rsurface.modelvertex3f_bufferoffset = 0;
8535                         rsurface.modelvertex3f_vertexbuffer = 0;
8536                         rsurface.modelvertex3f_bufferoffset = 0;
8537                         rsurface.modelsvector3f_vertexbuffer = 0;
8538                         rsurface.modelsvector3f_bufferoffset = 0;
8539                         rsurface.modeltvector3f_vertexbuffer = 0;
8540                         rsurface.modeltvector3f_bufferoffset = 0;
8541                         rsurface.modelnormal3f_vertexbuffer = 0;
8542                         rsurface.modelnormal3f_bufferoffset = 0;
8543                 }
8544                 else
8545                 {
8546                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8547                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8548                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8549                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8550                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8551                         rsurface.modelsvector3f = NULL;
8552                         rsurface.modeltvector3f = NULL;
8553                         rsurface.modelnormal3f = NULL;
8554                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8555                         rsurface.modelvertexmesh = NULL;
8556                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8557                         rsurface.modelvertexmesh_bufferoffset = 0;
8558                         rsurface.modelvertex3f_vertexbuffer = NULL;
8559                         rsurface.modelvertex3f_bufferoffset = 0;
8560                         rsurface.modelvertex3f_vertexbuffer = 0;
8561                         rsurface.modelvertex3f_bufferoffset = 0;
8562                         rsurface.modelsvector3f_vertexbuffer = 0;
8563                         rsurface.modelsvector3f_bufferoffset = 0;
8564                         rsurface.modeltvector3f_vertexbuffer = 0;
8565                         rsurface.modeltvector3f_bufferoffset = 0;
8566                         rsurface.modelnormal3f_vertexbuffer = 0;
8567                         rsurface.modelnormal3f_bufferoffset = 0;
8568                 }
8569                 rsurface.modelgeneratedvertex = true;
8570         }
8571         else
8572         {
8573                 if (rsurface.entityskeletaltransform3x4)
8574                 {
8575                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8576                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8577                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8578                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8579                 }
8580                 else
8581                 {
8582                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8583                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8584                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8585                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8586                 }
8587                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8588                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8589                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8590                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8591                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8592                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8593                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8594                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8595                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8596                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8597                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8598                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8599                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8600                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8601                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8602                 rsurface.modelgeneratedvertex = false;
8603         }
8604         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8605         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8606         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8607         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8608         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8609         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8610         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8611         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8612         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8613         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8614         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8615         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8616         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8617         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8618         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8619         rsurface.modelelement3i = model->surfmesh.data_element3i;
8620         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8621         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8622         rsurface.modelelement3s = model->surfmesh.data_element3s;
8623         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8624         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8625         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8626         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8627         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8628         rsurface.modelsurfaces = model->data_surfaces;
8629         rsurface.batchgeneratedvertex = false;
8630         rsurface.batchfirstvertex = 0;
8631         rsurface.batchnumvertices = 0;
8632         rsurface.batchfirsttriangle = 0;
8633         rsurface.batchnumtriangles = 0;
8634         rsurface.batchvertex3f  = NULL;
8635         rsurface.batchvertex3f_vertexbuffer = NULL;
8636         rsurface.batchvertex3f_bufferoffset = 0;
8637         rsurface.batchsvector3f = NULL;
8638         rsurface.batchsvector3f_vertexbuffer = NULL;
8639         rsurface.batchsvector3f_bufferoffset = 0;
8640         rsurface.batchtvector3f = NULL;
8641         rsurface.batchtvector3f_vertexbuffer = NULL;
8642         rsurface.batchtvector3f_bufferoffset = 0;
8643         rsurface.batchnormal3f  = NULL;
8644         rsurface.batchnormal3f_vertexbuffer = NULL;
8645         rsurface.batchnormal3f_bufferoffset = 0;
8646         rsurface.batchlightmapcolor4f = NULL;
8647         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8648         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8649         rsurface.batchtexcoordtexture2f = NULL;
8650         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8651         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8652         rsurface.batchtexcoordlightmap2f = NULL;
8653         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8654         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8655         rsurface.batchskeletalindex4ub = NULL;
8656         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8657         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8658         rsurface.batchskeletalweight4ub = NULL;
8659         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8660         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8661         rsurface.batchvertexmesh = NULL;
8662         rsurface.batchvertexmesh_vertexbuffer = NULL;
8663         rsurface.batchvertexmesh_bufferoffset = 0;
8664         rsurface.batchelement3i = NULL;
8665         rsurface.batchelement3i_indexbuffer = NULL;
8666         rsurface.batchelement3i_bufferoffset = 0;
8667         rsurface.batchelement3s = NULL;
8668         rsurface.batchelement3s_indexbuffer = NULL;
8669         rsurface.batchelement3s_bufferoffset = 0;
8670         rsurface.passcolor4f = NULL;
8671         rsurface.passcolor4f_vertexbuffer = NULL;
8672         rsurface.passcolor4f_bufferoffset = 0;
8673         rsurface.forcecurrenttextureupdate = false;
8674 }
8675
8676 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)
8677 {
8678         rsurface.entity = r_refdef.scene.worldentity;
8679         if (r != 1.0f || g != 1.0f || b != 1.0f || a != 1.0f) {
8680                 // HACK to provide a valid entity with modded colors to R_GetCurrentTexture.
8681                 // A better approach could be making this copy only once per frame.
8682                 static entity_render_t custom_entity;
8683                 int q;
8684                 custom_entity = *rsurface.entity;
8685                 for (q = 0; q < 3; ++q) {
8686                         float colormod = q == 0 ? r : q == 1 ? g : b;
8687                         custom_entity.render_fullbright[q] *= colormod;
8688                         custom_entity.render_modellight_ambient[q] *= colormod;
8689                         custom_entity.render_modellight_diffuse[q] *= colormod;
8690                         custom_entity.render_lightmap_ambient[q] *= colormod;
8691                         custom_entity.render_lightmap_diffuse[q] *= colormod;
8692                         custom_entity.render_rtlight_diffuse[q] *= colormod;
8693                 }
8694                 custom_entity.alpha *= a;
8695                 rsurface.entity = &custom_entity;
8696         }
8697         rsurface.skeleton = NULL;
8698         rsurface.ent_skinnum = 0;
8699         rsurface.ent_qwskin = -1;
8700         rsurface.ent_flags = entflags;
8701         rsurface.shadertime = r_refdef.scene.time - shadertime;
8702         rsurface.modelnumvertices = numvertices;
8703         rsurface.modelnumtriangles = numtriangles;
8704         rsurface.matrix = *matrix;
8705         rsurface.inversematrix = *inversematrix;
8706         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8707         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8708         R_EntityMatrix(&rsurface.matrix);
8709         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8710         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8711         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8712         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8713         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8714         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8715         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8716         rsurface.frameblend[0].lerp = 1;
8717         rsurface.ent_alttextures = false;
8718         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8719         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8720         rsurface.entityskeletaltransform3x4 = NULL;
8721         rsurface.entityskeletaltransform3x4buffer = NULL;
8722         rsurface.entityskeletaltransform3x4offset = 0;
8723         rsurface.entityskeletaltransform3x4size = 0;
8724         rsurface.entityskeletalnumtransforms = 0;
8725         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8726         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8727         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8728         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8729         if (wanttangents)
8730         {
8731                 rsurface.modelvertex3f = (float *)vertex3f;
8732                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8733                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8734                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8735         }
8736         else if (wantnormals)
8737         {
8738                 rsurface.modelvertex3f = (float *)vertex3f;
8739                 rsurface.modelsvector3f = NULL;
8740                 rsurface.modeltvector3f = NULL;
8741                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8742         }
8743         else
8744         {
8745                 rsurface.modelvertex3f = (float *)vertex3f;
8746                 rsurface.modelsvector3f = NULL;
8747                 rsurface.modeltvector3f = NULL;
8748                 rsurface.modelnormal3f = NULL;
8749         }
8750         rsurface.modelvertexmesh = NULL;
8751         rsurface.modelvertexmesh_vertexbuffer = NULL;
8752         rsurface.modelvertexmesh_bufferoffset = 0;
8753         rsurface.modelvertex3f_vertexbuffer = 0;
8754         rsurface.modelvertex3f_bufferoffset = 0;
8755         rsurface.modelsvector3f_vertexbuffer = 0;
8756         rsurface.modelsvector3f_bufferoffset = 0;
8757         rsurface.modeltvector3f_vertexbuffer = 0;
8758         rsurface.modeltvector3f_bufferoffset = 0;
8759         rsurface.modelnormal3f_vertexbuffer = 0;
8760         rsurface.modelnormal3f_bufferoffset = 0;
8761         rsurface.modelgeneratedvertex = true;
8762         rsurface.modellightmapcolor4f  = (float *)color4f;
8763         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8764         rsurface.modellightmapcolor4f_bufferoffset = 0;
8765         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8766         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8767         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8768         rsurface.modeltexcoordlightmap2f  = NULL;
8769         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8770         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8771         rsurface.modelskeletalindex4ub = NULL;
8772         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8773         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8774         rsurface.modelskeletalweight4ub = NULL;
8775         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8776         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8777         rsurface.modelelement3i = (int *)element3i;
8778         rsurface.modelelement3i_indexbuffer = NULL;
8779         rsurface.modelelement3i_bufferoffset = 0;
8780         rsurface.modelelement3s = (unsigned short *)element3s;
8781         rsurface.modelelement3s_indexbuffer = NULL;
8782         rsurface.modelelement3s_bufferoffset = 0;
8783         rsurface.modellightmapoffsets = NULL;
8784         rsurface.modelsurfaces = NULL;
8785         rsurface.batchgeneratedvertex = false;
8786         rsurface.batchfirstvertex = 0;
8787         rsurface.batchnumvertices = 0;
8788         rsurface.batchfirsttriangle = 0;
8789         rsurface.batchnumtriangles = 0;
8790         rsurface.batchvertex3f  = NULL;
8791         rsurface.batchvertex3f_vertexbuffer = NULL;
8792         rsurface.batchvertex3f_bufferoffset = 0;
8793         rsurface.batchsvector3f = NULL;
8794         rsurface.batchsvector3f_vertexbuffer = NULL;
8795         rsurface.batchsvector3f_bufferoffset = 0;
8796         rsurface.batchtvector3f = NULL;
8797         rsurface.batchtvector3f_vertexbuffer = NULL;
8798         rsurface.batchtvector3f_bufferoffset = 0;
8799         rsurface.batchnormal3f  = NULL;
8800         rsurface.batchnormal3f_vertexbuffer = NULL;
8801         rsurface.batchnormal3f_bufferoffset = 0;
8802         rsurface.batchlightmapcolor4f = NULL;
8803         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8804         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8805         rsurface.batchtexcoordtexture2f = NULL;
8806         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8807         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8808         rsurface.batchtexcoordlightmap2f = NULL;
8809         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8810         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8811         rsurface.batchskeletalindex4ub = NULL;
8812         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8813         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8814         rsurface.batchskeletalweight4ub = NULL;
8815         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8816         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8817         rsurface.batchvertexmesh = NULL;
8818         rsurface.batchvertexmesh_vertexbuffer = NULL;
8819         rsurface.batchvertexmesh_bufferoffset = 0;
8820         rsurface.batchelement3i = NULL;
8821         rsurface.batchelement3i_indexbuffer = NULL;
8822         rsurface.batchelement3i_bufferoffset = 0;
8823         rsurface.batchelement3s = NULL;
8824         rsurface.batchelement3s_indexbuffer = NULL;
8825         rsurface.batchelement3s_bufferoffset = 0;
8826         rsurface.passcolor4f = NULL;
8827         rsurface.passcolor4f_vertexbuffer = NULL;
8828         rsurface.passcolor4f_bufferoffset = 0;
8829         rsurface.forcecurrenttextureupdate = true;
8830
8831         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8832         {
8833                 if ((wantnormals || wanttangents) && !normal3f)
8834                 {
8835                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8836                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8837                 }
8838                 if (wanttangents && !svector3f)
8839                 {
8840                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8841                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8842                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8843                 }
8844         }
8845 }
8846
8847 float RSurf_FogPoint(const float *v)
8848 {
8849         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8850         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8851         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8852         float FogHeightFade = r_refdef.fogheightfade;
8853         float fogfrac;
8854         unsigned int fogmasktableindex;
8855         if (r_refdef.fogplaneviewabove)
8856                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8857         else
8858                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8859         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8860         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8861 }
8862
8863 float RSurf_FogVertex(const float *v)
8864 {
8865         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8866         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8867         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8868         float FogHeightFade = rsurface.fogheightfade;
8869         float fogfrac;
8870         unsigned int fogmasktableindex;
8871         if (r_refdef.fogplaneviewabove)
8872                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8873         else
8874                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8875         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8876         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8877 }
8878
8879 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8880 {
8881         int i;
8882         for (i = 0;i < numelements;i++)
8883                 outelement3i[i] = inelement3i[i] + adjust;
8884 }
8885
8886 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8887 extern cvar_t gl_vbo;
8888 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8889 {
8890         int deformindex;
8891         int firsttriangle;
8892         int numtriangles;
8893         int firstvertex;
8894         int endvertex;
8895         int numvertices;
8896         int surfacefirsttriangle;
8897         int surfacenumtriangles;
8898         int surfacefirstvertex;
8899         int surfaceendvertex;
8900         int surfacenumvertices;
8901         int batchnumsurfaces = texturenumsurfaces;
8902         int batchnumvertices;
8903         int batchnumtriangles;
8904         int needsupdate;
8905         int i, j;
8906         qboolean gaps;
8907         qboolean dynamicvertex;
8908         float amplitude;
8909         float animpos;
8910         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8911         float waveparms[4];
8912         unsigned char *ub;
8913         q3shaderinfo_deform_t *deform;
8914         const msurface_t *surface, *firstsurface;
8915         r_vertexmesh_t *vertexmesh;
8916         if (!texturenumsurfaces)
8917                 return;
8918         // find vertex range of this surface batch
8919         gaps = false;
8920         firstsurface = texturesurfacelist[0];
8921         firsttriangle = firstsurface->num_firsttriangle;
8922         batchnumvertices = 0;
8923         batchnumtriangles = 0;
8924         firstvertex = endvertex = firstsurface->num_firstvertex;
8925         for (i = 0;i < texturenumsurfaces;i++)
8926         {
8927                 surface = texturesurfacelist[i];
8928                 if (surface != firstsurface + i)
8929                         gaps = true;
8930                 surfacefirstvertex = surface->num_firstvertex;
8931                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8932                 surfacenumvertices = surface->num_vertices;
8933                 surfacenumtriangles = surface->num_triangles;
8934                 if (firstvertex > surfacefirstvertex)
8935                         firstvertex = surfacefirstvertex;
8936                 if (endvertex < surfaceendvertex)
8937                         endvertex = surfaceendvertex;
8938                 batchnumvertices += surfacenumvertices;
8939                 batchnumtriangles += surfacenumtriangles;
8940         }
8941
8942         r_refdef.stats[r_stat_batch_batches]++;
8943         if (gaps)
8944                 r_refdef.stats[r_stat_batch_withgaps]++;
8945         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8946         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8947         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8948
8949         // we now know the vertex range used, and if there are any gaps in it
8950         rsurface.batchfirstvertex = firstvertex;
8951         rsurface.batchnumvertices = endvertex - firstvertex;
8952         rsurface.batchfirsttriangle = firsttriangle;
8953         rsurface.batchnumtriangles = batchnumtriangles;
8954
8955         // this variable holds flags for which properties have been updated that
8956         // may require regenerating vertexmesh array...
8957         needsupdate = 0;
8958
8959         // check if any dynamic vertex processing must occur
8960         dynamicvertex = false;
8961
8962         // a cvar to force the dynamic vertex path to be taken, for debugging
8963         if (r_batch_debugdynamicvertexpath.integer)
8964         {
8965                 if (!dynamicvertex)
8966                 {
8967                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8968                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8969                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8970                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8971                 }
8972                 dynamicvertex = true;
8973         }
8974
8975         // if there is a chance of animated vertex colors, it's a dynamic batch
8976         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8977         {
8978                 if (!dynamicvertex)
8979                 {
8980                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8981                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8982                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8983                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8984                 }
8985                 dynamicvertex = true;
8986                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8987         }
8988
8989         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8990         {
8991                 switch (deform->deform)
8992                 {
8993                 default:
8994                 case Q3DEFORM_PROJECTIONSHADOW:
8995                 case Q3DEFORM_TEXT0:
8996                 case Q3DEFORM_TEXT1:
8997                 case Q3DEFORM_TEXT2:
8998                 case Q3DEFORM_TEXT3:
8999                 case Q3DEFORM_TEXT4:
9000                 case Q3DEFORM_TEXT5:
9001                 case Q3DEFORM_TEXT6:
9002                 case Q3DEFORM_TEXT7:
9003                 case Q3DEFORM_NONE:
9004                         break;
9005                 case Q3DEFORM_AUTOSPRITE:
9006                         if (!dynamicvertex)
9007                         {
9008                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9009                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9010                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9011                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9012                         }
9013                         dynamicvertex = true;
9014                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9015                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9016                         break;
9017                 case Q3DEFORM_AUTOSPRITE2:
9018                         if (!dynamicvertex)
9019                         {
9020                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9021                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9022                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9023                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9024                         }
9025                         dynamicvertex = true;
9026                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9027                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9028                         break;
9029                 case Q3DEFORM_NORMAL:
9030                         if (!dynamicvertex)
9031                         {
9032                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9033                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9034                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9035                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9036                         }
9037                         dynamicvertex = true;
9038                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9039                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9040                         break;
9041                 case Q3DEFORM_WAVE:
9042                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9043                                 break; // if wavefunc is a nop, ignore this transform
9044                         if (!dynamicvertex)
9045                         {
9046                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9047                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9048                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9049                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9050                         }
9051                         dynamicvertex = true;
9052                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9053                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9054                         break;
9055                 case Q3DEFORM_BULGE:
9056                         if (!dynamicvertex)
9057                         {
9058                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9059                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9060                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9061                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9062                         }
9063                         dynamicvertex = true;
9064                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9065                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9066                         break;
9067                 case Q3DEFORM_MOVE:
9068                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9069                                 break; // if wavefunc is a nop, ignore this transform
9070                         if (!dynamicvertex)
9071                         {
9072                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9073                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9074                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9075                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9076                         }
9077                         dynamicvertex = true;
9078                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9079                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9080                         break;
9081                 }
9082         }
9083         if (rsurface.texture->materialshaderpass)
9084         {
9085                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9086                 {
9087                 default:
9088                 case Q3TCGEN_TEXTURE:
9089                         break;
9090                 case Q3TCGEN_LIGHTMAP:
9091                         if (!dynamicvertex)
9092                         {
9093                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9094                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9095                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9096                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9097                         }
9098                         dynamicvertex = true;
9099                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9100                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9101                         break;
9102                 case Q3TCGEN_VECTOR:
9103                         if (!dynamicvertex)
9104                         {
9105                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9106                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9107                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9108                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9109                         }
9110                         dynamicvertex = true;
9111                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9112                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9113                         break;
9114                 case Q3TCGEN_ENVIRONMENT:
9115                         if (!dynamicvertex)
9116                         {
9117                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9118                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9119                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9120                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9121                         }
9122                         dynamicvertex = true;
9123                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9124                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9125                         break;
9126                 }
9127                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9128                 {
9129                         if (!dynamicvertex)
9130                         {
9131                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9132                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9133                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9134                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9135                         }
9136                         dynamicvertex = true;
9137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9138                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9139                 }
9140         }
9141
9142         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9143         {
9144                 if (!dynamicvertex)
9145                 {
9146                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9147                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9148                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9149                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9150                 }
9151                 dynamicvertex = true;
9152                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9153         }
9154
9155         // when the model data has no vertex buffer (dynamic mesh), we need to
9156         // eliminate gaps
9157         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9158                 batchneed |= BATCHNEED_NOGAPS;
9159
9160         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9161         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9162         // we ensure this by treating the vertex batch as dynamic...
9163         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9164         {
9165                 if (!dynamicvertex)
9166                 {
9167                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9168                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9169                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9170                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9171                 }
9172                 dynamicvertex = true;
9173         }
9174
9175         if (dynamicvertex)
9176         {
9177                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9178                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9179                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9180                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9181                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9182                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9183                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9184                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9185         }
9186
9187         // if needsupdate, we have to do a dynamic vertex batch for sure
9188         if (needsupdate & batchneed)
9189         {
9190                 if (!dynamicvertex)
9191                 {
9192                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9193                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9194                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9195                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9196                 }
9197                 dynamicvertex = true;
9198         }
9199
9200         // see if we need to build vertexmesh from arrays
9201         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9202         {
9203                 if (!dynamicvertex)
9204                 {
9205                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9206                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9207                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9208                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9209                 }
9210                 dynamicvertex = true;
9211         }
9212
9213         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9214         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9215                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9216
9217         rsurface.batchvertex3f = rsurface.modelvertex3f;
9218         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9219         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9220         rsurface.batchsvector3f = rsurface.modelsvector3f;
9221         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9222         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9223         rsurface.batchtvector3f = rsurface.modeltvector3f;
9224         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9225         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9226         rsurface.batchnormal3f = rsurface.modelnormal3f;
9227         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9228         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9229         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9230         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9231         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9232         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9233         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9234         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9235         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9236         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9237         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9238         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9239         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9240         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9241         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9242         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9243         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9244         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9245         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9246         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9247         rsurface.batchelement3i = rsurface.modelelement3i;
9248         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9249         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9250         rsurface.batchelement3s = rsurface.modelelement3s;
9251         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9252         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9253         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9254         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9255         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9256         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9257         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9258
9259         // if any dynamic vertex processing has to occur in software, we copy the
9260         // entire surface list together before processing to rebase the vertices
9261         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9262         //
9263         // if any gaps exist and we do not have a static vertex buffer, we have to
9264         // copy the surface list together to avoid wasting upload bandwidth on the
9265         // vertices in the gaps.
9266         //
9267         // if gaps exist and we have a static vertex buffer, we can choose whether
9268         // to combine the index buffer ranges into one dynamic index buffer or
9269         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9270         //
9271         // in many cases the batch is reduced to one draw call.
9272
9273         rsurface.batchmultidraw = false;
9274         rsurface.batchmultidrawnumsurfaces = 0;
9275         rsurface.batchmultidrawsurfacelist = NULL;
9276
9277         if (!dynamicvertex)
9278         {
9279                 // static vertex data, just set pointers...
9280                 rsurface.batchgeneratedvertex = false;
9281                 // if there are gaps, we want to build a combined index buffer,
9282                 // otherwise use the original static buffer with an appropriate offset
9283                 if (gaps)
9284                 {
9285                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9286                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9287                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9288                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9289                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9290                         {
9291                                 rsurface.batchmultidraw = true;
9292                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9293                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9294                                 return;
9295                         }
9296                         // build a new triangle elements array for this batch
9297                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9298                         rsurface.batchfirsttriangle = 0;
9299                         numtriangles = 0;
9300                         for (i = 0;i < texturenumsurfaces;i++)
9301                         {
9302                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9303                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9304                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9305                                 numtriangles += surfacenumtriangles;
9306                         }
9307                         rsurface.batchelement3i_indexbuffer = NULL;
9308                         rsurface.batchelement3i_bufferoffset = 0;
9309                         rsurface.batchelement3s = NULL;
9310                         rsurface.batchelement3s_indexbuffer = NULL;
9311                         rsurface.batchelement3s_bufferoffset = 0;
9312                         if (endvertex <= 65536)
9313                         {
9314                                 // make a 16bit (unsigned short) index array if possible
9315                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9316                                 for (i = 0;i < numtriangles*3;i++)
9317                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9318                         }
9319                         // upload buffer data for the copytriangles batch
9320                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9321                         {
9322                                 if (rsurface.batchelement3s)
9323                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9324                                 else if (rsurface.batchelement3i)
9325                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9326                         }
9327                 }
9328                 else
9329                 {
9330                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9331                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9332                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9333                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9334                 }
9335                 return;
9336         }
9337
9338         // something needs software processing, do it for real...
9339         // we only directly handle separate array data in this case and then
9340         // generate interleaved data if needed...
9341         rsurface.batchgeneratedvertex = true;
9342         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9343         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9344         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9345         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9346
9347         // now copy the vertex data into a combined array and make an index array
9348         // (this is what Quake3 does all the time)
9349         // we also apply any skeletal animation here that would have been done in
9350         // the vertex shader, because most of the dynamic vertex animation cases
9351         // need actual vertex positions and normals
9352         //if (dynamicvertex)
9353         {
9354                 rsurface.batchvertexmesh = NULL;
9355                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9356                 rsurface.batchvertexmesh_bufferoffset = 0;
9357                 rsurface.batchvertex3f = NULL;
9358                 rsurface.batchvertex3f_vertexbuffer = NULL;
9359                 rsurface.batchvertex3f_bufferoffset = 0;
9360                 rsurface.batchsvector3f = NULL;
9361                 rsurface.batchsvector3f_vertexbuffer = NULL;
9362                 rsurface.batchsvector3f_bufferoffset = 0;
9363                 rsurface.batchtvector3f = NULL;
9364                 rsurface.batchtvector3f_vertexbuffer = NULL;
9365                 rsurface.batchtvector3f_bufferoffset = 0;
9366                 rsurface.batchnormal3f = NULL;
9367                 rsurface.batchnormal3f_vertexbuffer = NULL;
9368                 rsurface.batchnormal3f_bufferoffset = 0;
9369                 rsurface.batchlightmapcolor4f = NULL;
9370                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9371                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9372                 rsurface.batchtexcoordtexture2f = NULL;
9373                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9374                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9375                 rsurface.batchtexcoordlightmap2f = NULL;
9376                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9377                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9378                 rsurface.batchskeletalindex4ub = NULL;
9379                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9380                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9381                 rsurface.batchskeletalweight4ub = NULL;
9382                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9383                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9384                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9385                 rsurface.batchelement3i_indexbuffer = NULL;
9386                 rsurface.batchelement3i_bufferoffset = 0;
9387                 rsurface.batchelement3s = NULL;
9388                 rsurface.batchelement3s_indexbuffer = NULL;
9389                 rsurface.batchelement3s_bufferoffset = 0;
9390                 rsurface.batchskeletaltransform3x4buffer = NULL;
9391                 rsurface.batchskeletaltransform3x4offset = 0;
9392                 rsurface.batchskeletaltransform3x4size = 0;
9393                 // we'll only be setting up certain arrays as needed
9394                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9395                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9396                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9397                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9398                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9399                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9400                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9401                 {
9402                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9403                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9404                 }
9405                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9406                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9407                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9408                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9409                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9410                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9411                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9412                 {
9413                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9414                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9415                 }
9416                 numvertices = 0;
9417                 numtriangles = 0;
9418                 for (i = 0;i < texturenumsurfaces;i++)
9419                 {
9420                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9421                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9422                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9423                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9424                         // copy only the data requested
9425                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9426                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9427                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9428                         {
9429                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9430                                 {
9431                                         if (rsurface.batchvertex3f)
9432                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9433                                         else
9434                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9435                                 }
9436                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9437                                 {
9438                                         if (rsurface.modelnormal3f)
9439                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9440                                         else
9441                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9442                                 }
9443                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9444                                 {
9445                                         if (rsurface.modelsvector3f)
9446                                         {
9447                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9448                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9449                                         }
9450                                         else
9451                                         {
9452                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9453                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9454                                         }
9455                                 }
9456                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9457                                 {
9458                                         if (rsurface.modellightmapcolor4f)
9459                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9460                                         else
9461                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9462                                 }
9463                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9464                                 {
9465                                         if (rsurface.modeltexcoordtexture2f)
9466                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9467                                         else
9468                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9469                                 }
9470                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9471                                 {
9472                                         if (rsurface.modeltexcoordlightmap2f)
9473                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9474                                         else
9475                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9476                                 }
9477                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9478                                 {
9479                                         if (rsurface.modelskeletalindex4ub)
9480                                         {
9481                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9482                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9483                                         }
9484                                         else
9485                                         {
9486                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9487                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9488                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9489                                                 for (j = 0;j < surfacenumvertices;j++)
9490                                                         ub[j*4] = 255;
9491                                         }
9492                                 }
9493                         }
9494                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9495                         numvertices += surfacenumvertices;
9496                         numtriangles += surfacenumtriangles;
9497                 }
9498
9499                 // generate a 16bit index array as well if possible
9500                 // (in general, dynamic batches fit)
9501                 if (numvertices <= 65536)
9502                 {
9503                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9504                         for (i = 0;i < numtriangles*3;i++)
9505                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9506                 }
9507
9508                 // since we've copied everything, the batch now starts at 0
9509                 rsurface.batchfirstvertex = 0;
9510                 rsurface.batchnumvertices = batchnumvertices;
9511                 rsurface.batchfirsttriangle = 0;
9512                 rsurface.batchnumtriangles = batchnumtriangles;
9513         }
9514
9515         // apply skeletal animation that would have been done in the vertex shader
9516         if (rsurface.batchskeletaltransform3x4)
9517         {
9518                 const unsigned char *si;
9519                 const unsigned char *sw;
9520                 const float *t[4];
9521                 const float *b = rsurface.batchskeletaltransform3x4;
9522                 float *vp, *vs, *vt, *vn;
9523                 float w[4];
9524                 float m[3][4], n[3][4];
9525                 float tp[3], ts[3], tt[3], tn[3];
9526                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9527                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9528                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9529                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9530                 si = rsurface.batchskeletalindex4ub;
9531                 sw = rsurface.batchskeletalweight4ub;
9532                 vp = rsurface.batchvertex3f;
9533                 vs = rsurface.batchsvector3f;
9534                 vt = rsurface.batchtvector3f;
9535                 vn = rsurface.batchnormal3f;
9536                 memset(m[0], 0, sizeof(m));
9537                 memset(n[0], 0, sizeof(n));
9538                 for (i = 0;i < batchnumvertices;i++)
9539                 {
9540                         t[0] = b + si[0]*12;
9541                         if (sw[0] == 255)
9542                         {
9543                                 // common case - only one matrix
9544                                 m[0][0] = t[0][ 0];
9545                                 m[0][1] = t[0][ 1];
9546                                 m[0][2] = t[0][ 2];
9547                                 m[0][3] = t[0][ 3];
9548                                 m[1][0] = t[0][ 4];
9549                                 m[1][1] = t[0][ 5];
9550                                 m[1][2] = t[0][ 6];
9551                                 m[1][3] = t[0][ 7];
9552                                 m[2][0] = t[0][ 8];
9553                                 m[2][1] = t[0][ 9];
9554                                 m[2][2] = t[0][10];
9555                                 m[2][3] = t[0][11];
9556                         }
9557                         else if (sw[2] + sw[3])
9558                         {
9559                                 // blend 4 matrices
9560                                 t[1] = b + si[1]*12;
9561                                 t[2] = b + si[2]*12;
9562                                 t[3] = b + si[3]*12;
9563                                 w[0] = sw[0] * (1.0f / 255.0f);
9564                                 w[1] = sw[1] * (1.0f / 255.0f);
9565                                 w[2] = sw[2] * (1.0f / 255.0f);
9566                                 w[3] = sw[3] * (1.0f / 255.0f);
9567                                 // blend the matrices
9568                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9569                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9570                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9571                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9572                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9573                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9574                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9575                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9576                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9577                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9578                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9579                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9580                         }
9581                         else
9582                         {
9583                                 // blend 2 matrices
9584                                 t[1] = b + si[1]*12;
9585                                 w[0] = sw[0] * (1.0f / 255.0f);
9586                                 w[1] = sw[1] * (1.0f / 255.0f);
9587                                 // blend the matrices
9588                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9589                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9590                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9591                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9592                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9593                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9594                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9595                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9596                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9597                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9598                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9599                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9600                         }
9601                         si += 4;
9602                         sw += 4;
9603                         // modify the vertex
9604                         VectorCopy(vp, tp);
9605                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9606                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9607                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9608                         vp += 3;
9609                         if (vn)
9610                         {
9611                                 // the normal transformation matrix is a set of cross products...
9612                                 CrossProduct(m[1], m[2], n[0]);
9613                                 CrossProduct(m[2], m[0], n[1]);
9614                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9615                                 VectorCopy(vn, tn);
9616                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9617                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9618                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9619                                 VectorNormalize(vn);
9620                                 vn += 3;
9621                                 if (vs)
9622                                 {
9623                                         VectorCopy(vs, ts);
9624                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9625                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9626                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9627                                         VectorNormalize(vs);
9628                                         vs += 3;
9629                                         VectorCopy(vt, tt);
9630                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9631                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9632                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9633                                         VectorNormalize(vt);
9634                                         vt += 3;
9635                                 }
9636                         }
9637                 }
9638                 rsurface.batchskeletaltransform3x4 = NULL;
9639                 rsurface.batchskeletalnumtransforms = 0;
9640         }
9641
9642         // q1bsp surfaces rendered in vertex color mode have to have colors
9643         // calculated based on lightstyles
9644         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9645         {
9646                 // generate color arrays for the surfaces in this list
9647                 int c[4];
9648                 int scale;
9649                 int size3;
9650                 const int *offsets;
9651                 const unsigned char *lm;
9652                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9653                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9654                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9655                 numvertices = 0;
9656                 for (i = 0;i < texturenumsurfaces;i++)
9657                 {
9658                         surface = texturesurfacelist[i];
9659                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9660                         surfacenumvertices = surface->num_vertices;
9661                         if (surface->lightmapinfo->samples)
9662                         {
9663                                 for (j = 0;j < surfacenumvertices;j++)
9664                                 {
9665                                         lm = surface->lightmapinfo->samples + offsets[j];
9666                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9667                                         VectorScale(lm, scale, c);
9668                                         if (surface->lightmapinfo->styles[1] != 255)
9669                                         {
9670                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9671                                                 lm += size3;
9672                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9673                                                 VectorMA(c, scale, lm, c);
9674                                                 if (surface->lightmapinfo->styles[2] != 255)
9675                                                 {
9676                                                         lm += size3;
9677                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9678                                                         VectorMA(c, scale, lm, c);
9679                                                         if (surface->lightmapinfo->styles[3] != 255)
9680                                                         {
9681                                                                 lm += size3;
9682                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9683                                                                 VectorMA(c, scale, lm, c);
9684                                                         }
9685                                                 }
9686                                         }
9687                                         c[0] >>= 7;
9688                                         c[1] >>= 7;
9689                                         c[2] >>= 7;
9690                                         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);
9691                                         numvertices++;
9692                                 }
9693                         }
9694                         else
9695                         {
9696                                 for (j = 0;j < surfacenumvertices;j++)
9697                                 {
9698                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9699                                         numvertices++;
9700                                 }
9701                         }
9702                 }
9703         }
9704
9705         // if vertices are deformed (sprite flares and things in maps, possibly
9706         // water waves, bulges and other deformations), modify the copied vertices
9707         // in place
9708         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9709         {
9710                 float scale;
9711                 switch (deform->deform)
9712                 {
9713                 default:
9714                 case Q3DEFORM_PROJECTIONSHADOW:
9715                 case Q3DEFORM_TEXT0:
9716                 case Q3DEFORM_TEXT1:
9717                 case Q3DEFORM_TEXT2:
9718                 case Q3DEFORM_TEXT3:
9719                 case Q3DEFORM_TEXT4:
9720                 case Q3DEFORM_TEXT5:
9721                 case Q3DEFORM_TEXT6:
9722                 case Q3DEFORM_TEXT7:
9723                 case Q3DEFORM_NONE:
9724                         break;
9725                 case Q3DEFORM_AUTOSPRITE:
9726                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9727                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9728                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9729                         VectorNormalize(newforward);
9730                         VectorNormalize(newright);
9731                         VectorNormalize(newup);
9732 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9733 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9734 //                      rsurface.batchvertex3f_bufferoffset = 0;
9735 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9736 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9737 //                      rsurface.batchsvector3f_bufferoffset = 0;
9738 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9739 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9740 //                      rsurface.batchtvector3f_bufferoffset = 0;
9741 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9742 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9743 //                      rsurface.batchnormal3f_bufferoffset = 0;
9744                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9745                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9746                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9747                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9748                                 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);
9749                         // a single autosprite surface can contain multiple sprites...
9750                         for (j = 0;j < batchnumvertices - 3;j += 4)
9751                         {
9752                                 VectorClear(center);
9753                                 for (i = 0;i < 4;i++)
9754                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9755                                 VectorScale(center, 0.25f, center);
9756                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9757                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9758                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9759                                 for (i = 0;i < 4;i++)
9760                                 {
9761                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9762                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9763                                 }
9764                         }
9765                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9766                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9767                         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);
9768                         break;
9769                 case Q3DEFORM_AUTOSPRITE2:
9770                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9771                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9772                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9773                         VectorNormalize(newforward);
9774                         VectorNormalize(newright);
9775                         VectorNormalize(newup);
9776 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9777 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9778 //                      rsurface.batchvertex3f_bufferoffset = 0;
9779                         {
9780                                 const float *v1, *v2;
9781                                 vec3_t start, end;
9782                                 float f, l;
9783                                 struct
9784                                 {
9785                                         float length2;
9786                                         const float *v1;
9787                                         const float *v2;
9788                                 }
9789                                 shortest[2];
9790                                 memset(shortest, 0, sizeof(shortest));
9791                                 // a single autosprite surface can contain multiple sprites...
9792                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9793                                 {
9794                                         VectorClear(center);
9795                                         for (i = 0;i < 4;i++)
9796                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9797                                         VectorScale(center, 0.25f, center);
9798                                         // find the two shortest edges, then use them to define the
9799                                         // axis vectors for rotating around the central axis
9800                                         for (i = 0;i < 6;i++)
9801                                         {
9802                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9803                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9804                                                 l = VectorDistance2(v1, v2);
9805                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9806                                                 if (v1[2] != v2[2])
9807                                                         l += (1.0f / 1024.0f);
9808                                                 if (shortest[0].length2 > l || i == 0)
9809                                                 {
9810                                                         shortest[1] = shortest[0];
9811                                                         shortest[0].length2 = l;
9812                                                         shortest[0].v1 = v1;
9813                                                         shortest[0].v2 = v2;
9814                                                 }
9815                                                 else if (shortest[1].length2 > l || i == 1)
9816                                                 {
9817                                                         shortest[1].length2 = l;
9818                                                         shortest[1].v1 = v1;
9819                                                         shortest[1].v2 = v2;
9820                                                 }
9821                                         }
9822                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9823                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9824                                         // this calculates the right vector from the shortest edge
9825                                         // and the up vector from the edge midpoints
9826                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9827                                         VectorNormalize(right);
9828                                         VectorSubtract(end, start, up);
9829                                         VectorNormalize(up);
9830                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9831                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9832                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9833                                         VectorNegate(forward, forward);
9834                                         VectorReflect(forward, 0, up, forward);
9835                                         VectorNormalize(forward);
9836                                         CrossProduct(up, forward, newright);
9837                                         VectorNormalize(newright);
9838                                         // rotate the quad around the up axis vector, this is made
9839                                         // especially easy by the fact we know the quad is flat,
9840                                         // so we only have to subtract the center position and
9841                                         // measure distance along the right vector, and then
9842                                         // multiply that by the newright vector and add back the
9843                                         // center position
9844                                         // we also need to subtract the old position to undo the
9845                                         // displacement from the center, which we do with a
9846                                         // DotProduct, the subtraction/addition of center is also
9847                                         // optimized into DotProducts here
9848                                         l = DotProduct(right, center);
9849                                         for (i = 0;i < 4;i++)
9850                                         {
9851                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9852                                                 f = DotProduct(right, v1) - l;
9853                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9854                                         }
9855                                 }
9856                         }
9857                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9858                         {
9859 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9860 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9861 //                              rsurface.batchnormal3f_bufferoffset = 0;
9862                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9863                         }
9864                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9865                         {
9866 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9867 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9868 //                              rsurface.batchsvector3f_bufferoffset = 0;
9869 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9870 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9871 //                              rsurface.batchtvector3f_bufferoffset = 0;
9872                                 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);
9873                         }
9874                         break;
9875                 case Q3DEFORM_NORMAL:
9876                         // deform the normals to make reflections wavey
9877                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9878                         rsurface.batchnormal3f_vertexbuffer = NULL;
9879                         rsurface.batchnormal3f_bufferoffset = 0;
9880                         for (j = 0;j < batchnumvertices;j++)
9881                         {
9882                                 float vertex[3];
9883                                 float *normal = rsurface.batchnormal3f + 3*j;
9884                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9885                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9886                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9887                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9888                                 VectorNormalize(normal);
9889                         }
9890                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9891                         {
9892 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9893 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9894 //                              rsurface.batchsvector3f_bufferoffset = 0;
9895 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9896 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9897 //                              rsurface.batchtvector3f_bufferoffset = 0;
9898                                 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);
9899                         }
9900                         break;
9901                 case Q3DEFORM_WAVE:
9902                         // deform vertex array to make wavey water and flags and such
9903                         waveparms[0] = deform->waveparms[0];
9904                         waveparms[1] = deform->waveparms[1];
9905                         waveparms[2] = deform->waveparms[2];
9906                         waveparms[3] = deform->waveparms[3];
9907                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9908                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9909                         // this is how a divisor of vertex influence on deformation
9910                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9911                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9912 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9913 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9914 //                      rsurface.batchvertex3f_bufferoffset = 0;
9915 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9916 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9917 //                      rsurface.batchnormal3f_bufferoffset = 0;
9918                         for (j = 0;j < batchnumvertices;j++)
9919                         {
9920                                 // if the wavefunc depends on time, evaluate it per-vertex
9921                                 if (waveparms[3])
9922                                 {
9923                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9924                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9925                                 }
9926                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9927                         }
9928                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9929                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9930                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9931                         {
9932 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9933 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9934 //                              rsurface.batchsvector3f_bufferoffset = 0;
9935 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9936 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9937 //                              rsurface.batchtvector3f_bufferoffset = 0;
9938                                 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);
9939                         }
9940                         break;
9941                 case Q3DEFORM_BULGE:
9942                         // deform vertex array to make the surface have moving bulges
9943 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9944 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9945 //                      rsurface.batchvertex3f_bufferoffset = 0;
9946 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9947 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9948 //                      rsurface.batchnormal3f_bufferoffset = 0;
9949                         for (j = 0;j < batchnumvertices;j++)
9950                         {
9951                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9952                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9953                         }
9954                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9955                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9956                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9957                         {
9958 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9959 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9960 //                              rsurface.batchsvector3f_bufferoffset = 0;
9961 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9962 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9963 //                              rsurface.batchtvector3f_bufferoffset = 0;
9964                                 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);
9965                         }
9966                         break;
9967                 case Q3DEFORM_MOVE:
9968                         // deform vertex array
9969                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9970                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9971                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9972                         VectorScale(deform->parms, scale, waveparms);
9973 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9974 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9975 //                      rsurface.batchvertex3f_bufferoffset = 0;
9976                         for (j = 0;j < batchnumvertices;j++)
9977                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9978                         break;
9979                 }
9980         }
9981
9982         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9983         {
9984         // generate texcoords based on the chosen texcoord source
9985                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9986                 {
9987                 default:
9988                 case Q3TCGEN_TEXTURE:
9989                         break;
9990                 case Q3TCGEN_LIGHTMAP:
9991         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9992         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9993         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9994                         if (rsurface.batchtexcoordlightmap2f)
9995                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9996                         break;
9997                 case Q3TCGEN_VECTOR:
9998         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9999         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10000         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10001                         for (j = 0;j < batchnumvertices;j++)
10002                         {
10003                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10004                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10005                         }
10006                         break;
10007                 case Q3TCGEN_ENVIRONMENT:
10008                         // make environment reflections using a spheremap
10009                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10010                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10011                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10012                         for (j = 0;j < batchnumvertices;j++)
10013                         {
10014                                 // identical to Q3A's method, but executed in worldspace so
10015                                 // carried models can be shiny too
10016
10017                                 float viewer[3], d, reflected[3], worldreflected[3];
10018
10019                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10020                                 // VectorNormalize(viewer);
10021
10022                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10023
10024                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10025                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10026                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10027                                 // note: this is proportinal to viewer, so we can normalize later
10028
10029                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10030                                 VectorNormalize(worldreflected);
10031
10032                                 // note: this sphere map only uses world x and z!
10033                                 // so positive and negative y will LOOK THE SAME.
10034                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10035                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10036                         }
10037                         break;
10038                 }
10039                 // the only tcmod that needs software vertex processing is turbulent, so
10040                 // check for it here and apply the changes if needed
10041                 // and we only support that as the first one
10042                 // (handling a mixture of turbulent and other tcmods would be problematic
10043                 //  without punting it entirely to a software path)
10044                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10045                 {
10046                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10047                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10048         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10049         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10050         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10051                         for (j = 0;j < batchnumvertices;j++)
10052                         {
10053                                 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);
10054                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10055                         }
10056                 }
10057         }
10058
10059         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10060         {
10061                 // convert the modified arrays to vertex structs
10062 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10063 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10064 //              rsurface.batchvertexmesh_bufferoffset = 0;
10065                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10066                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10067                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10068                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10069                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10070                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10071                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10072                 {
10073                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10074                         {
10075                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10076                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10077                         }
10078                 }
10079                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10080                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10081                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10082                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10083                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10084                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10085                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10086                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10087                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10088                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10089                 {
10090                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10091                         {
10092                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10093                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10094                         }
10095                 }
10096         }
10097
10098         // upload buffer data for the dynamic batch
10099         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10100         {
10101                 if (rsurface.batchvertexmesh)
10102                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10103                 else
10104                 {
10105                         if (rsurface.batchvertex3f)
10106                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10107                         if (rsurface.batchsvector3f)
10108                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10109                         if (rsurface.batchtvector3f)
10110                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10111                         if (rsurface.batchnormal3f)
10112                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10113                         if (rsurface.batchlightmapcolor4f)
10114                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10115                         if (rsurface.batchtexcoordtexture2f)
10116                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10117                         if (rsurface.batchtexcoordlightmap2f)
10118                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10119                         if (rsurface.batchskeletalindex4ub)
10120                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10121                         if (rsurface.batchskeletalweight4ub)
10122                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10123                 }
10124                 if (rsurface.batchelement3s)
10125                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10126                 else if (rsurface.batchelement3i)
10127                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10128         }
10129 }
10130
10131 void RSurf_DrawBatch(void)
10132 {
10133         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10134         // through the pipeline, killing it earlier in the pipeline would have
10135         // per-surface overhead rather than per-batch overhead, so it's best to
10136         // reject it here, before it hits glDraw.
10137         if (rsurface.batchnumtriangles == 0)
10138                 return;
10139 #if 0
10140         // batch debugging code
10141         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10142         {
10143                 int i;
10144                 int j;
10145                 int c;
10146                 const int *e;
10147                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10148                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10149                 {
10150                         c = e[i];
10151                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10152                         {
10153                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10154                                 {
10155                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10156                                                 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);
10157                                         break;
10158                                 }
10159                         }
10160                 }
10161         }
10162 #endif
10163         if (rsurface.batchmultidraw)
10164         {
10165                 // issue multiple draws rather than copying index data
10166                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10167                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10168                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10169                 for (i = 0;i < numsurfaces;)
10170                 {
10171                         // combine consecutive surfaces as one draw
10172                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10173                                 if (surfacelist[j] != surfacelist[k] + 1)
10174                                         break;
10175                         firstvertex = surfacelist[i]->num_firstvertex;
10176                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10177                         firsttriangle = surfacelist[i]->num_firsttriangle;
10178                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10179                         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);
10180                         i = j;
10181                 }
10182         }
10183         else
10184         {
10185                 // there is only one consecutive run of index data (may have been combined)
10186                 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);
10187         }
10188 }
10189
10190 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10191 {
10192         // pick the closest matching water plane
10193         int planeindex, vertexindex, bestplaneindex = -1;
10194         float d, bestd;
10195         vec3_t vert;
10196         const float *v;
10197         r_waterstate_waterplane_t *p;
10198         qboolean prepared = false;
10199         bestd = 0;
10200         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10201         {
10202                 if(p->camera_entity != rsurface.texture->camera_entity)
10203                         continue;
10204                 d = 0;
10205                 if(!prepared)
10206                 {
10207                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10208                         prepared = true;
10209                         if(rsurface.batchnumvertices == 0)
10210                                 break;
10211                 }
10212                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10213                 {
10214                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10215                         d += fabs(PlaneDiff(vert, &p->plane));
10216                 }
10217                 if (bestd > d || bestplaneindex < 0)
10218                 {
10219                         bestd = d;
10220                         bestplaneindex = planeindex;
10221                 }
10222         }
10223         return bestplaneindex;
10224         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10225         // this situation though, as it might be better to render single larger
10226         // batches with useless stuff (backface culled for example) than to
10227         // render multiple smaller batches
10228 }
10229
10230 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10231 {
10232         int i;
10233         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10234         rsurface.passcolor4f_vertexbuffer = 0;
10235         rsurface.passcolor4f_bufferoffset = 0;
10236         for (i = 0;i < rsurface.batchnumvertices;i++)
10237                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10238 }
10239
10240 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10241 {
10242         int i;
10243         float f;
10244         const float *v;
10245         const float *c;
10246         float *c2;
10247         if (rsurface.passcolor4f)
10248         {
10249                 // generate color arrays
10250                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10251                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10252                 rsurface.passcolor4f_vertexbuffer = 0;
10253                 rsurface.passcolor4f_bufferoffset = 0;
10254                 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)
10255                 {
10256                         f = RSurf_FogVertex(v);
10257                         c2[0] = c[0] * f;
10258                         c2[1] = c[1] * f;
10259                         c2[2] = c[2] * f;
10260                         c2[3] = c[3];
10261                 }
10262         }
10263         else
10264         {
10265                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10266                 rsurface.passcolor4f_vertexbuffer = 0;
10267                 rsurface.passcolor4f_bufferoffset = 0;
10268                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10269                 {
10270                         f = RSurf_FogVertex(v);
10271                         c2[0] = f;
10272                         c2[1] = f;
10273                         c2[2] = f;
10274                         c2[3] = 1;
10275                 }
10276         }
10277 }
10278
10279 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10280 {
10281         int i;
10282         float f;
10283         const float *v;
10284         const float *c;
10285         float *c2;
10286         if (!rsurface.passcolor4f)
10287                 return;
10288         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10289         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10290         rsurface.passcolor4f_vertexbuffer = 0;
10291         rsurface.passcolor4f_bufferoffset = 0;
10292         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)
10293         {
10294                 f = RSurf_FogVertex(v);
10295                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10296                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10297                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10298                 c2[3] = c[3];
10299         }
10300 }
10301
10302 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10303 {
10304         int i;
10305         const float *c;
10306         float *c2;
10307         if (!rsurface.passcolor4f)
10308                 return;
10309         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10310         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10311         rsurface.passcolor4f_vertexbuffer = 0;
10312         rsurface.passcolor4f_bufferoffset = 0;
10313         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10314         {
10315                 c2[0] = c[0] * r;
10316                 c2[1] = c[1] * g;
10317                 c2[2] = c[2] * b;
10318                 c2[3] = c[3] * a;
10319         }
10320 }
10321
10322 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10323 {
10324         int i;
10325         const float *c;
10326         float *c2;
10327         if (!rsurface.passcolor4f)
10328                 return;
10329         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10330         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10331         rsurface.passcolor4f_vertexbuffer = 0;
10332         rsurface.passcolor4f_bufferoffset = 0;
10333         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10334         {
10335                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10336                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10337                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10338                 c2[3] = c[3];
10339         }
10340 }
10341
10342 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10343 {
10344         // TODO: optimize
10345         rsurface.passcolor4f = NULL;
10346         rsurface.passcolor4f_vertexbuffer = 0;
10347         rsurface.passcolor4f_bufferoffset = 0;
10348         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10349         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10350         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10351         GL_Color(r, g, b, a);
10352         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10353         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10354         R_Mesh_TexMatrix(0, NULL);
10355         RSurf_DrawBatch();
10356 }
10357
10358 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10359 {
10360         // TODO: optimize applyfog && applycolor case
10361         // just apply fog if necessary, and tint the fog color array if necessary
10362         rsurface.passcolor4f = NULL;
10363         rsurface.passcolor4f_vertexbuffer = 0;
10364         rsurface.passcolor4f_bufferoffset = 0;
10365         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10366         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10367         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10368         GL_Color(r, g, b, a);
10369         RSurf_DrawBatch();
10370 }
10371
10372 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10373 {
10374         // TODO: optimize
10375         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10376         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10377         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10378         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10379         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10380         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10381         GL_Color(r, g, b, a);
10382         RSurf_DrawBatch();
10383 }
10384
10385 static void RSurf_DrawBatch_GL11_ClampColor(void)
10386 {
10387         int i;
10388         const float *c1;
10389         float *c2;
10390         if (!rsurface.passcolor4f)
10391                 return;
10392         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10393         {
10394                 c2[0] = bound(0.0f, c1[0], 1.0f);
10395                 c2[1] = bound(0.0f, c1[1], 1.0f);
10396                 c2[2] = bound(0.0f, c1[2], 1.0f);
10397                 c2[3] = bound(0.0f, c1[3], 1.0f);
10398         }
10399 }
10400
10401 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10402 {
10403         int i;
10404         float f;
10405         const float *v;
10406         const float *n;
10407         float *c;
10408         //vec3_t eyedir;
10409
10410         // fake shading
10411         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412         rsurface.passcolor4f_vertexbuffer = 0;
10413         rsurface.passcolor4f_bufferoffset = 0;
10414         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)
10415         {
10416                 f = -DotProduct(r_refdef.view.forward, n);
10417                 f = max(0, f);
10418                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10419                 f *= fakelightintensity;
10420                 Vector4Set(c, f, f, f, 1);
10421         }
10422 }
10423
10424 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10425 {
10426         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10427         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10428         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10429         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10430         GL_Color(r, g, b, a);
10431         RSurf_DrawBatch();
10432 }
10433
10434 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10435 {
10436         int i;
10437         float f;
10438         float alpha;
10439         const float *v;
10440         const float *n;
10441         float *c;
10442         vec3_t ambientcolor;
10443         vec3_t diffusecolor;
10444         vec3_t lightdir;
10445         // TODO: optimize
10446         // model lighting
10447         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10448         f = 0.5f * lightmapintensity;
10449         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10450         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10451         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10452         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10453         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10454         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10455         alpha = *a;
10456         if (VectorLength2(diffusecolor) > 0)
10457         {
10458                 // q3-style directional shading
10459                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10460                 rsurface.passcolor4f_vertexbuffer = 0;
10461                 rsurface.passcolor4f_bufferoffset = 0;
10462                 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)
10463                 {
10464                         if ((f = DotProduct(n, lightdir)) > 0)
10465                                 VectorMA(ambientcolor, f, diffusecolor, c);
10466                         else
10467                                 VectorCopy(ambientcolor, c);
10468                         c[3] = alpha;
10469                 }
10470                 *r = 1;
10471                 *g = 1;
10472                 *b = 1;
10473                 *a = 1;
10474                 *applycolor = false;
10475         }
10476         else
10477         {
10478                 *r = ambientcolor[0];
10479                 *g = ambientcolor[1];
10480                 *b = ambientcolor[2];
10481                 rsurface.passcolor4f = NULL;
10482                 rsurface.passcolor4f_vertexbuffer = 0;
10483                 rsurface.passcolor4f_bufferoffset = 0;
10484         }
10485 }
10486
10487 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10488 {
10489         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10490         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10491         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10492         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10493         GL_Color(r, g, b, a);
10494         RSurf_DrawBatch();
10495 }
10496
10497 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10498 {
10499         int i;
10500         float f;
10501         const float *v;
10502         float *c;
10503
10504         // fake shading
10505         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10506         rsurface.passcolor4f_vertexbuffer = 0;
10507         rsurface.passcolor4f_bufferoffset = 0;
10508
10509         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10510         {
10511                 f = 1 - RSurf_FogVertex(v);
10512                 c[0] = r;
10513                 c[1] = g;
10514                 c[2] = b;
10515                 c[3] = f * a;
10516         }
10517 }
10518
10519 void RSurf_SetupDepthAndCulling(void)
10520 {
10521         // submodels are biased to avoid z-fighting with world surfaces that they
10522         // may be exactly overlapping (avoids z-fighting artifacts on certain
10523         // doors and things in Quake maps)
10524         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10525         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10526         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10527         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10528 }
10529
10530 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10531 {
10532         int i, j;
10533         // transparent sky would be ridiculous
10534         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10535                 return;
10536         R_SetupShader_Generic_NoTexture(false, false);
10537         skyrenderlater = true;
10538         RSurf_SetupDepthAndCulling();
10539         GL_DepthMask(true);
10540
10541         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10542         if (r_sky_scissor.integer)
10543         {
10544                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10545                 for (i = 0; i < texturenumsurfaces; i++)
10546                 {
10547                         const msurface_t *surf = texturesurfacelist[i];
10548                         const float *v;
10549                         float p[3];
10550                         float mins[3], maxs[3];
10551                         int scissor[4];
10552                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10553                         {
10554                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10555                                 if (j > 0)
10556                                 {
10557                                         if (mins[0] > p[0]) mins[0] = p[0];
10558                                         if (mins[1] > p[1]) mins[1] = p[1];
10559                                         if (mins[2] > p[2]) mins[2] = p[2];
10560                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10561                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10562                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10563                                 }
10564                                 else
10565                                 {
10566                                         VectorCopy(p, mins);
10567                                         VectorCopy(p, maxs);
10568                                 }
10569                         }
10570                         if (!R_ScissorForBBox(mins, maxs, scissor))
10571                         {
10572                                 if (skyscissor[2])
10573                                 {
10574                                         if (skyscissor[0] > scissor[0])
10575                                         {
10576                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10577                                                 skyscissor[0] = scissor[0];
10578                                         }
10579                                         if (skyscissor[1] > scissor[1])
10580                                         {
10581                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10582                                                 skyscissor[1] = scissor[1];
10583                                         }
10584                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10585                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10586                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10587                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10588                                 }
10589                                 else
10590                                         Vector4Copy(scissor, skyscissor);
10591                         }
10592                 }
10593         }
10594
10595         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10596         // skymasking on them, and Quake3 never did sky masking (unlike
10597         // software Quake and software Quake2), so disable the sky masking
10598         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10599         // and skymasking also looks very bad when noclipping outside the
10600         // level, so don't use it then either.
10601         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)
10602         {
10603                 R_Mesh_ResetTextureState();
10604                 if (skyrendermasked)
10605                 {
10606                         R_SetupShader_DepthOrShadow(false, false, false);
10607                         // depth-only (masking)
10608                         GL_ColorMask(0, 0, 0, 0);
10609                         // just to make sure that braindead drivers don't draw
10610                         // anything despite that colormask...
10611                         GL_BlendFunc(GL_ZERO, GL_ONE);
10612                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10613                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10614                 }
10615                 else
10616                 {
10617                         R_SetupShader_Generic_NoTexture(false, false);
10618                         // fog sky
10619                         GL_BlendFunc(GL_ONE, GL_ZERO);
10620                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10621                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10622                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10623                 }
10624                 RSurf_DrawBatch();
10625                 if (skyrendermasked)
10626                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10627         }
10628         R_Mesh_ResetTextureState();
10629         GL_Color(1, 1, 1, 1);
10630 }
10631
10632 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10633 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10634 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10635 {
10636         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10637                 return;
10638         if (prepass)
10639         {
10640                 // render screenspace normalmap to texture
10641                 GL_DepthMask(true);
10642                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10643                 RSurf_DrawBatch();
10644                 return;
10645         }
10646
10647         // bind lightmap texture
10648
10649         // water/refraction/reflection/camera surfaces have to be handled specially
10650         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10651         {
10652                 int start, end, startplaneindex;
10653                 for (start = 0;start < texturenumsurfaces;start = end)
10654                 {
10655                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10656                         if(startplaneindex < 0)
10657                         {
10658                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10659                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10660                                 end = start + 1;
10661                                 continue;
10662                         }
10663                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10664                                 ;
10665                         // now that we have a batch using the same planeindex, render it
10666                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10667                         {
10668                                 // render water or distortion background
10669                                 GL_DepthMask(true);
10670                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10671                                 RSurf_DrawBatch();
10672                                 // blend surface on top
10673                                 GL_DepthMask(false);
10674                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10675                                 RSurf_DrawBatch();
10676                         }
10677                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10678                         {
10679                                 // render surface with reflection texture as input
10680                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10681                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10682                                 RSurf_DrawBatch();
10683                         }
10684                 }
10685                 return;
10686         }
10687
10688         // render surface batch normally
10689         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10690         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10691         RSurf_DrawBatch();
10692 }
10693
10694 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10695 {
10696         // OpenGL 1.3 path - anything not completely ancient
10697         qboolean applycolor;
10698         qboolean applyfog;
10699         int layerindex;
10700         const texturelayer_t *layer;
10701         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);
10702         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10703
10704         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10705         {
10706                 vec4_t layercolor;
10707                 int layertexrgbscale;
10708                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10709                 {
10710                         if (layerindex == 0)
10711                                 GL_AlphaTest(true);
10712                         else
10713                         {
10714                                 GL_AlphaTest(false);
10715                                 GL_DepthFunc(GL_EQUAL);
10716                         }
10717                 }
10718                 GL_DepthMask(layer->depthmask && writedepth);
10719                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10720                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10721                 {
10722                         layertexrgbscale = 4;
10723                         VectorScale(layer->color, 0.25f, layercolor);
10724                 }
10725                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10726                 {
10727                         layertexrgbscale = 2;
10728                         VectorScale(layer->color, 0.5f, layercolor);
10729                 }
10730                 else
10731                 {
10732                         layertexrgbscale = 1;
10733                         VectorScale(layer->color, 1.0f, layercolor);
10734                 }
10735                 layercolor[3] = layer->color[3];
10736                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10737                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10738                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10739                 switch (layer->type)
10740                 {
10741                 case TEXTURELAYERTYPE_LITTEXTURE:
10742                         // single-pass lightmapped texture with 2x rgbscale
10743                         R_Mesh_TexBind(0, r_texture_white);
10744                         R_Mesh_TexMatrix(0, NULL);
10745                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10746                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10747                         R_Mesh_TexBind(1, layer->texture);
10748                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10749                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10750                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10751                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10752                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10753                         else if (FAKELIGHT_ENABLED)
10754                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10755                         else if (rsurface.uselightmaptexture)
10756                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10757                         else
10758                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10759                         break;
10760                 case TEXTURELAYERTYPE_TEXTURE:
10761                         // singletexture unlit texture with transparency support
10762                         R_Mesh_TexBind(0, layer->texture);
10763                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10764                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10765                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10766                         R_Mesh_TexBind(1, 0);
10767                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10768                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10769                         break;
10770                 case TEXTURELAYERTYPE_FOG:
10771                         // singletexture fogging
10772                         if (layer->texture)
10773                         {
10774                                 R_Mesh_TexBind(0, layer->texture);
10775                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10776                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10777                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10778                         }
10779                         else
10780                         {
10781                                 R_Mesh_TexBind(0, 0);
10782                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10783                         }
10784                         R_Mesh_TexBind(1, 0);
10785                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10786                         // generate a color array for the fog pass
10787                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10788                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10789                         RSurf_DrawBatch();
10790                         break;
10791                 default:
10792                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10793                 }
10794         }
10795         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10796         {
10797                 GL_DepthFunc(GL_LEQUAL);
10798                 GL_AlphaTest(false);
10799         }
10800 }
10801
10802 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10803 {
10804         // OpenGL 1.1 - crusty old voodoo path
10805         qboolean applyfog;
10806         int layerindex;
10807         const texturelayer_t *layer;
10808         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);
10809         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10810
10811         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10812         {
10813                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10814                 {
10815                         if (layerindex == 0)
10816                                 GL_AlphaTest(true);
10817                         else
10818                         {
10819                                 GL_AlphaTest(false);
10820                                 GL_DepthFunc(GL_EQUAL);
10821                         }
10822                 }
10823                 GL_DepthMask(layer->depthmask && writedepth);
10824                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10825                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10826                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10827                 switch (layer->type)
10828                 {
10829                 case TEXTURELAYERTYPE_LITTEXTURE:
10830                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10831                         {
10832                                 // two-pass lit texture with 2x rgbscale
10833                                 // first the lightmap pass
10834                                 R_Mesh_TexBind(0, r_texture_white);
10835                                 R_Mesh_TexMatrix(0, NULL);
10836                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10837                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10838                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10839                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10840                                 else if (FAKELIGHT_ENABLED)
10841                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10842                                 else if (rsurface.uselightmaptexture)
10843                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10844                                 else
10845                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10846                                 // then apply the texture to it
10847                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10848                                 R_Mesh_TexBind(0, layer->texture);
10849                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10850                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10851                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10852                                 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);
10853                         }
10854                         else
10855                         {
10856                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10857                                 R_Mesh_TexBind(0, layer->texture);
10858                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10859                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10860                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10861                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10862                                         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);
10863                                 else if (FAKELIGHT_ENABLED)
10864                                         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);
10865                                 else
10866                                         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);
10867                         }
10868                         break;
10869                 case TEXTURELAYERTYPE_TEXTURE:
10870                         // singletexture unlit texture with transparency support
10871                         R_Mesh_TexBind(0, layer->texture);
10872                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10873                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10874                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10875                         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);
10876                         break;
10877                 case TEXTURELAYERTYPE_FOG:
10878                         // singletexture fogging
10879                         if (layer->texture)
10880                         {
10881                                 R_Mesh_TexBind(0, layer->texture);
10882                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10883                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10884                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10885                         }
10886                         else
10887                         {
10888                                 R_Mesh_TexBind(0, 0);
10889                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10890                         }
10891                         // generate a color array for the fog pass
10892                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10893                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10894                         RSurf_DrawBatch();
10895                         break;
10896                 default:
10897                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10898                 }
10899         }
10900         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10901         {
10902                 GL_DepthFunc(GL_LEQUAL);
10903                 GL_AlphaTest(false);
10904         }
10905 }
10906
10907 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10908 {
10909         int vi;
10910         int j;
10911         r_vertexgeneric_t *batchvertex;
10912         float c[4];
10913         texture_t *t = rsurface.texture;
10914
10915 //      R_Mesh_ResetTextureState();
10916         R_SetupShader_Generic_NoTexture(false, false);
10917
10918         if(t && t->currentskinframe)
10919         {
10920                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10921                 c[3] *= t->currentalpha;
10922         }
10923         else
10924         {
10925                 c[0] = 1;
10926                 c[1] = 0;
10927                 c[2] = 1;
10928                 c[3] = 1;
10929         }
10930
10931         if (t->pantstexture || t->shirttexture)
10932         {
10933                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10934                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10935                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10936         }
10937
10938         // brighten it up (as texture value 127 means "unlit")
10939         c[0] *= 2 * r_refdef.view.colorscale;
10940         c[1] *= 2 * r_refdef.view.colorscale;
10941         c[2] *= 2 * r_refdef.view.colorscale;
10942
10943         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10944                 c[3] *= r_wateralpha.value;
10945
10946         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10947         {
10948                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10949                 GL_DepthMask(false);
10950         }
10951         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10952         {
10953                 GL_BlendFunc(GL_ONE, GL_ONE);
10954                 GL_DepthMask(false);
10955         }
10956         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10957         {
10958                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10959                 GL_DepthMask(false);
10960         }
10961         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10962         {
10963                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10964                 GL_DepthMask(false);
10965         }
10966         else
10967         {
10968                 GL_BlendFunc(GL_ONE, GL_ZERO);
10969                 GL_DepthMask(writedepth);
10970         }
10971
10972         if (r_showsurfaces.integer == 3)
10973         {
10974                 rsurface.passcolor4f = NULL;
10975
10976                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10977                 {
10978                         qboolean applycolor = true;
10979                         float one = 1.0;
10980
10981                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10982
10983                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10984                 }
10985                 else if (FAKELIGHT_ENABLED)
10986                 {
10987                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10988
10989                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10990                 }
10991                 else
10992                 {
10993                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10994
10995                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10996                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10997                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10998                         RSurf_DrawBatch_GL11_ApplyAmbient();
10999                 }
11000
11001                 if(!rsurface.passcolor4f)
11002                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11003
11004                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11005                 if(r_refdef.fogenabled)
11006                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11007                 RSurf_DrawBatch_GL11_ClampColor();
11008
11009                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11010                 R_SetupShader_Generic_NoTexture(false, false);
11011                 RSurf_DrawBatch();
11012         }
11013         else if (!r_refdef.view.showdebug)
11014         {
11015                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11016                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11017                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11018                 {
11019                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11020                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11021                 }
11022                 R_Mesh_PrepareVertices_Generic_Unlock();
11023                 RSurf_DrawBatch();
11024         }
11025         else if (r_showsurfaces.integer == 4)
11026         {
11027                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11028                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11029                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11030                 {
11031                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11032                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11033                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11034                 }
11035                 R_Mesh_PrepareVertices_Generic_Unlock();
11036                 RSurf_DrawBatch();
11037         }
11038         else if (r_showsurfaces.integer == 2)
11039         {
11040                 const int *e;
11041                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11042                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11043                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11044                 {
11045                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11046                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11047                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11048                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11049                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11050                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11051                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11052                 }
11053                 R_Mesh_PrepareVertices_Generic_Unlock();
11054                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11055         }
11056         else
11057         {
11058                 int texturesurfaceindex;
11059                 int k;
11060                 const msurface_t *surface;
11061                 float surfacecolor4f[4];
11062                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11063                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11064                 vi = 0;
11065                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11066                 {
11067                         surface = texturesurfacelist[texturesurfaceindex];
11068                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11069                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11070                         for (j = 0;j < surface->num_vertices;j++)
11071                         {
11072                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11073                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11074                                 vi++;
11075                         }
11076                 }
11077                 R_Mesh_PrepareVertices_Generic_Unlock();
11078                 RSurf_DrawBatch();
11079         }
11080 }
11081
11082 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11083 {
11084         CHECKGLERROR
11085         RSurf_SetupDepthAndCulling();
11086         if (r_showsurfaces.integer)
11087         {
11088                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11089                 return;
11090         }
11091         switch (vid.renderpath)
11092         {
11093         case RENDERPATH_GL20:
11094         case RENDERPATH_D3D9:
11095         case RENDERPATH_D3D10:
11096         case RENDERPATH_D3D11:
11097         case RENDERPATH_SOFT:
11098         case RENDERPATH_GLES2:
11099                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11100                 break;
11101         case RENDERPATH_GL13:
11102         case RENDERPATH_GLES1:
11103                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11104                 break;
11105         case RENDERPATH_GL11:
11106                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11107                 break;
11108         }
11109         CHECKGLERROR
11110 }
11111
11112 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11113 {
11114         int i, j;
11115         int texturenumsurfaces, endsurface;
11116         texture_t *texture;
11117         const msurface_t *surface;
11118         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11119
11120         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11121                 RSurf_ActiveModelEntity(ent, false, false, false);
11122         else
11123         {
11124                 switch (vid.renderpath)
11125                 {
11126                 case RENDERPATH_GL20:
11127                 case RENDERPATH_D3D9:
11128                 case RENDERPATH_D3D10:
11129                 case RENDERPATH_D3D11:
11130                 case RENDERPATH_SOFT:
11131                 case RENDERPATH_GLES2:
11132                         RSurf_ActiveModelEntity(ent, true, true, false);
11133                         break;
11134                 case RENDERPATH_GL11:
11135                 case RENDERPATH_GL13:
11136                 case RENDERPATH_GLES1:
11137                         RSurf_ActiveModelEntity(ent, true, false, false);
11138                         break;
11139                 }
11140         }
11141
11142         if (r_transparentdepthmasking.integer)
11143         {
11144                 qboolean setup = false;
11145                 for (i = 0;i < numsurfaces;i = j)
11146                 {
11147                         j = i + 1;
11148                         surface = rsurface.modelsurfaces + surfacelist[i];
11149                         texture = surface->texture;
11150                         rsurface.texture = R_GetCurrentTexture(texture);
11151                         rsurface.lightmaptexture = NULL;
11152                         rsurface.deluxemaptexture = NULL;
11153                         rsurface.uselightmaptexture = false;
11154                         // scan ahead until we find a different texture
11155                         endsurface = min(i + 1024, numsurfaces);
11156                         texturenumsurfaces = 0;
11157                         texturesurfacelist[texturenumsurfaces++] = surface;
11158                         for (;j < endsurface;j++)
11159                         {
11160                                 surface = rsurface.modelsurfaces + surfacelist[j];
11161                                 if (texture != surface->texture)
11162                                         break;
11163                                 texturesurfacelist[texturenumsurfaces++] = surface;
11164                         }
11165                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11166                                 continue;
11167                         // render the range of surfaces as depth
11168                         if (!setup)
11169                         {
11170                                 setup = true;
11171                                 GL_ColorMask(0,0,0,0);
11172                                 GL_Color(1,1,1,1);
11173                                 GL_DepthTest(true);
11174                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11175                                 GL_DepthMask(true);
11176 //                              R_Mesh_ResetTextureState();
11177                         }
11178                         RSurf_SetupDepthAndCulling();
11179                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11180                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11181                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11182                         RSurf_DrawBatch();
11183                 }
11184                 if (setup)
11185                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11186         }
11187
11188         for (i = 0;i < numsurfaces;i = j)
11189         {
11190                 j = i + 1;
11191                 surface = rsurface.modelsurfaces + surfacelist[i];
11192                 texture = surface->texture;
11193                 rsurface.texture = R_GetCurrentTexture(texture);
11194                 // scan ahead until we find a different texture
11195                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11196                 texturenumsurfaces = 0;
11197                 texturesurfacelist[texturenumsurfaces++] = surface;
11198                 if(FAKELIGHT_ENABLED)
11199                 {
11200                         rsurface.lightmaptexture = NULL;
11201                         rsurface.deluxemaptexture = NULL;
11202                         rsurface.uselightmaptexture = false;
11203                         for (;j < endsurface;j++)
11204                         {
11205                                 surface = rsurface.modelsurfaces + surfacelist[j];
11206                                 if (texture != surface->texture)
11207                                         break;
11208                                 texturesurfacelist[texturenumsurfaces++] = surface;
11209                         }
11210                 }
11211                 else
11212                 {
11213                         rsurface.lightmaptexture = surface->lightmaptexture;
11214                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11215                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11216                         for (;j < endsurface;j++)
11217                         {
11218                                 surface = rsurface.modelsurfaces + surfacelist[j];
11219                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11220                                         break;
11221                                 texturesurfacelist[texturenumsurfaces++] = surface;
11222                         }
11223                 }
11224                 // render the range of surfaces
11225                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11226         }
11227         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11228 }
11229
11230 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11231 {
11232         // transparent surfaces get pushed off into the transparent queue
11233         int surfacelistindex;
11234         const msurface_t *surface;
11235         vec3_t tempcenter, center;
11236         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11237         {
11238                 surface = texturesurfacelist[surfacelistindex];
11239                 if (r_transparent_sortsurfacesbynearest.integer)
11240                 {
11241                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11242                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11243                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11244                 }
11245                 else
11246                 {
11247                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11248                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11249                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11250                 }
11251                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11252                 if (rsurface.entity->transparent_offset) // transparent offset
11253                 {
11254                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11255                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11256                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11257                 }
11258                 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);
11259         }
11260 }
11261
11262 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11263 {
11264         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11265                 return;
11266         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11267                 return;
11268         RSurf_SetupDepthAndCulling();
11269         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11270         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11271         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11272         RSurf_DrawBatch();
11273 }
11274
11275 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11276 {
11277         CHECKGLERROR
11278         if (depthonly)
11279                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11280         else if (prepass)
11281         {
11282                 if (!rsurface.texture->currentnumlayers)
11283                         return;
11284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11285                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11286                 else
11287                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11288         }
11289         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11290                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11291         else if (!rsurface.texture->currentnumlayers)
11292                 return;
11293         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11294         {
11295                 // in the deferred case, transparent surfaces were queued during prepass
11296                 if (!r_shadow_usingdeferredprepass)
11297                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11298         }
11299         else
11300         {
11301                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11302                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11303         }
11304         CHECKGLERROR
11305 }
11306
11307 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11308 {
11309         int i, j;
11310         texture_t *texture;
11311         R_FrameData_SetMark();
11312         // break the surface list down into batches by texture and use of lightmapping
11313         for (i = 0;i < numsurfaces;i = j)
11314         {
11315                 j = i + 1;
11316                 // texture is the base texture pointer, rsurface.texture is the
11317                 // current frame/skin the texture is directing us to use (for example
11318                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11319                 // use skin 1 instead)
11320                 texture = surfacelist[i]->texture;
11321                 rsurface.texture = R_GetCurrentTexture(texture);
11322                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11323                 {
11324                         // if this texture is not the kind we want, skip ahead to the next one
11325                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11326                                 ;
11327                         continue;
11328                 }
11329                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11330                 {
11331                         rsurface.lightmaptexture = NULL;
11332                         rsurface.deluxemaptexture = NULL;
11333                         rsurface.uselightmaptexture = false;
11334                         // simply scan ahead until we find a different texture or lightmap state
11335                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11336                                 ;
11337                 }
11338                 else
11339                 {
11340                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11341                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11342                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11343                         // simply scan ahead until we find a different texture or lightmap state
11344                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11345                                 ;
11346                 }
11347                 // render the range of surfaces
11348                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11349         }
11350         R_FrameData_ReturnToMark();
11351 }
11352
11353 float locboxvertex3f[6*4*3] =
11354 {
11355         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11356         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11357         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11358         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11359         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11360         1,0,0, 0,0,0, 0,1,0, 1,1,0
11361 };
11362
11363 unsigned short locboxelements[6*2*3] =
11364 {
11365          0, 1, 2, 0, 2, 3,
11366          4, 5, 6, 4, 6, 7,
11367          8, 9,10, 8,10,11,
11368         12,13,14, 12,14,15,
11369         16,17,18, 16,18,19,
11370         20,21,22, 20,22,23
11371 };
11372
11373 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11374 {
11375         int i, j;
11376         cl_locnode_t *loc = (cl_locnode_t *)ent;
11377         vec3_t mins, size;
11378         float vertex3f[6*4*3];
11379         CHECKGLERROR
11380         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11381         GL_DepthMask(false);
11382         GL_DepthRange(0, 1);
11383         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11384         GL_DepthTest(true);
11385         GL_CullFace(GL_NONE);
11386         R_EntityMatrix(&identitymatrix);
11387
11388 //      R_Mesh_ResetTextureState();
11389
11390         i = surfacelist[0];
11391         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11392                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11393                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11394                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11395
11396         if (VectorCompare(loc->mins, loc->maxs))
11397         {
11398                 VectorSet(size, 2, 2, 2);
11399                 VectorMA(loc->mins, -0.5f, size, mins);
11400         }
11401         else
11402         {
11403                 VectorCopy(loc->mins, mins);
11404                 VectorSubtract(loc->maxs, loc->mins, size);
11405         }
11406
11407         for (i = 0;i < 6*4*3;)
11408                 for (j = 0;j < 3;j++, i++)
11409                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11410
11411         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11412         R_SetupShader_Generic_NoTexture(false, false);
11413         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11414 }
11415
11416 void R_DrawLocs(void)
11417 {
11418         int index;
11419         cl_locnode_t *loc, *nearestloc;
11420         vec3_t center;
11421         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11422         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11423         {
11424                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11425                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11426         }
11427 }
11428
11429 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11430 {
11431         if (decalsystem->decals)
11432                 Mem_Free(decalsystem->decals);
11433         memset(decalsystem, 0, sizeof(*decalsystem));
11434 }
11435
11436 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)
11437 {
11438         tridecal_t *decal;
11439         tridecal_t *decals;
11440         int i;
11441
11442         // expand or initialize the system
11443         if (decalsystem->maxdecals <= decalsystem->numdecals)
11444         {
11445                 decalsystem_t old = *decalsystem;
11446                 qboolean useshortelements;
11447                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11448                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11449                 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)));
11450                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11451                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11452                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11453                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11454                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11455                 if (decalsystem->numdecals)
11456                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11457                 if (old.decals)
11458                         Mem_Free(old.decals);
11459                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11460                         decalsystem->element3i[i] = i;
11461                 if (useshortelements)
11462                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11463                                 decalsystem->element3s[i] = i;
11464         }
11465
11466         // grab a decal and search for another free slot for the next one
11467         decals = decalsystem->decals;
11468         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11469         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11470                 ;
11471         decalsystem->freedecal = i;
11472         if (decalsystem->numdecals <= i)
11473                 decalsystem->numdecals = i + 1;
11474
11475         // initialize the decal
11476         decal->lived = 0;
11477         decal->triangleindex = triangleindex;
11478         decal->surfaceindex = surfaceindex;
11479         decal->decalsequence = decalsequence;
11480         decal->color4f[0][0] = c0[0];
11481         decal->color4f[0][1] = c0[1];
11482         decal->color4f[0][2] = c0[2];
11483         decal->color4f[0][3] = 1;
11484         decal->color4f[1][0] = c1[0];
11485         decal->color4f[1][1] = c1[1];
11486         decal->color4f[1][2] = c1[2];
11487         decal->color4f[1][3] = 1;
11488         decal->color4f[2][0] = c2[0];
11489         decal->color4f[2][1] = c2[1];
11490         decal->color4f[2][2] = c2[2];
11491         decal->color4f[2][3] = 1;
11492         decal->vertex3f[0][0] = v0[0];
11493         decal->vertex3f[0][1] = v0[1];
11494         decal->vertex3f[0][2] = v0[2];
11495         decal->vertex3f[1][0] = v1[0];
11496         decal->vertex3f[1][1] = v1[1];
11497         decal->vertex3f[1][2] = v1[2];
11498         decal->vertex3f[2][0] = v2[0];
11499         decal->vertex3f[2][1] = v2[1];
11500         decal->vertex3f[2][2] = v2[2];
11501         decal->texcoord2f[0][0] = t0[0];
11502         decal->texcoord2f[0][1] = t0[1];
11503         decal->texcoord2f[1][0] = t1[0];
11504         decal->texcoord2f[1][1] = t1[1];
11505         decal->texcoord2f[2][0] = t2[0];
11506         decal->texcoord2f[2][1] = t2[1];
11507         TriangleNormal(v0, v1, v2, decal->plane);
11508         VectorNormalize(decal->plane);
11509         decal->plane[3] = DotProduct(v0, decal->plane);
11510 }
11511
11512 extern cvar_t cl_decals_bias;
11513 extern cvar_t cl_decals_models;
11514 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11515 // baseparms, parms, temps
11516 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)
11517 {
11518         int cornerindex;
11519         int index;
11520         float v[9][3];
11521         const float *vertex3f;
11522         const float *normal3f;
11523         int numpoints;
11524         float points[2][9][3];
11525         float temp[3];
11526         float tc[9][2];
11527         float f;
11528         float c[9][4];
11529         const int *e;
11530
11531         e = rsurface.modelelement3i + 3*triangleindex;
11532
11533         vertex3f = rsurface.modelvertex3f;
11534         normal3f = rsurface.modelnormal3f;
11535
11536         if (normal3f)
11537         {
11538                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11539                 {
11540                         index = 3*e[cornerindex];
11541                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11542                 }
11543         }
11544         else
11545         {
11546                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11547                 {
11548                         index = 3*e[cornerindex];
11549                         VectorCopy(vertex3f + index, v[cornerindex]);
11550                 }
11551         }
11552
11553         // cull backfaces
11554         //TriangleNormal(v[0], v[1], v[2], normal);
11555         //if (DotProduct(normal, localnormal) < 0.0f)
11556         //      continue;
11557         // clip by each of the box planes formed from the projection matrix
11558         // if anything survives, we emit the decal
11559         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]);
11560         if (numpoints < 3)
11561                 return;
11562         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]);
11563         if (numpoints < 3)
11564                 return;
11565         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]);
11566         if (numpoints < 3)
11567                 return;
11568         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]);
11569         if (numpoints < 3)
11570                 return;
11571         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]);
11572         if (numpoints < 3)
11573                 return;
11574         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]);
11575         if (numpoints < 3)
11576                 return;
11577         // some part of the triangle survived, so we have to accept it...
11578         if (dynamic)
11579         {
11580                 // dynamic always uses the original triangle
11581                 numpoints = 3;
11582                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11583                 {
11584                         index = 3*e[cornerindex];
11585                         VectorCopy(vertex3f + index, v[cornerindex]);
11586                 }
11587         }
11588         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11589         {
11590                 // convert vertex positions to texcoords
11591                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11592                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11593                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11594                 // calculate distance fade from the projection origin
11595                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11596                 f = bound(0.0f, f, 1.0f);
11597                 c[cornerindex][0] = r * f;
11598                 c[cornerindex][1] = g * f;
11599                 c[cornerindex][2] = b * f;
11600                 c[cornerindex][3] = 1.0f;
11601                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11602         }
11603         if (dynamic)
11604                 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);
11605         else
11606                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11607                         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);
11608 }
11609 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)
11610 {
11611         matrix4x4_t projection;
11612         decalsystem_t *decalsystem;
11613         qboolean dynamic;
11614         dp_model_t *model;
11615         const msurface_t *surface;
11616         const msurface_t *surfaces;
11617         const int *surfacelist;
11618         const texture_t *texture;
11619         int numtriangles;
11620         int numsurfacelist;
11621         int surfacelistindex;
11622         int surfaceindex;
11623         int triangleindex;
11624         float localorigin[3];
11625         float localnormal[3];
11626         float localmins[3];
11627         float localmaxs[3];
11628         float localsize;
11629         //float normal[3];
11630         float planes[6][4];
11631         float angles[3];
11632         bih_t *bih;
11633         int bih_triangles_count;
11634         int bih_triangles[256];
11635         int bih_surfaces[256];
11636
11637         decalsystem = &ent->decalsystem;
11638         model = ent->model;
11639         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11640         {
11641                 R_DecalSystem_Reset(&ent->decalsystem);
11642                 return;
11643         }
11644
11645         if (!model->brush.data_leafs && !cl_decals_models.integer)
11646         {
11647                 if (decalsystem->model)
11648                         R_DecalSystem_Reset(decalsystem);
11649                 return;
11650         }
11651
11652         if (decalsystem->model != model)
11653                 R_DecalSystem_Reset(decalsystem);
11654         decalsystem->model = model;
11655
11656         RSurf_ActiveModelEntity(ent, true, false, false);
11657
11658         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11659         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11660         VectorNormalize(localnormal);
11661         localsize = worldsize*rsurface.inversematrixscale;
11662         localmins[0] = localorigin[0] - localsize;
11663         localmins[1] = localorigin[1] - localsize;
11664         localmins[2] = localorigin[2] - localsize;
11665         localmaxs[0] = localorigin[0] + localsize;
11666         localmaxs[1] = localorigin[1] + localsize;
11667         localmaxs[2] = localorigin[2] + localsize;
11668
11669         //VectorCopy(localnormal, planes[4]);
11670         //VectorVectors(planes[4], planes[2], planes[0]);
11671         AnglesFromVectors(angles, localnormal, NULL, false);
11672         AngleVectors(angles, planes[0], planes[2], planes[4]);
11673         VectorNegate(planes[0], planes[1]);
11674         VectorNegate(planes[2], planes[3]);
11675         VectorNegate(planes[4], planes[5]);
11676         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11677         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11678         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11679         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11680         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11681         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11682
11683 #if 1
11684 // works
11685 {
11686         matrix4x4_t forwardprojection;
11687         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11688         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11689 }
11690 #else
11691 // broken
11692 {
11693         float projectionvector[4][3];
11694         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11695         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11696         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11697         projectionvector[0][0] = planes[0][0] * ilocalsize;
11698         projectionvector[0][1] = planes[1][0] * ilocalsize;
11699         projectionvector[0][2] = planes[2][0] * ilocalsize;
11700         projectionvector[1][0] = planes[0][1] * ilocalsize;
11701         projectionvector[1][1] = planes[1][1] * ilocalsize;
11702         projectionvector[1][2] = planes[2][1] * ilocalsize;
11703         projectionvector[2][0] = planes[0][2] * ilocalsize;
11704         projectionvector[2][1] = planes[1][2] * ilocalsize;
11705         projectionvector[2][2] = planes[2][2] * ilocalsize;
11706         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11707         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11708         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11709         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11710 }
11711 #endif
11712
11713         dynamic = model->surfmesh.isanimated;
11714         numsurfacelist = model->nummodelsurfaces;
11715         surfacelist = model->sortedmodelsurfaces;
11716         surfaces = model->data_surfaces;
11717
11718         bih = NULL;
11719         bih_triangles_count = -1;
11720         if(!dynamic)
11721         {
11722                 if(model->render_bih.numleafs)
11723                         bih = &model->render_bih;
11724                 else if(model->collision_bih.numleafs)
11725                         bih = &model->collision_bih;
11726         }
11727         if(bih)
11728                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11729         if(bih_triangles_count == 0)
11730                 return;
11731         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11732                 return;
11733         if(bih_triangles_count > 0)
11734         {
11735                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11736                 {
11737                         surfaceindex = bih_surfaces[triangleindex];
11738                         surface = surfaces + surfaceindex;
11739                         texture = surface->texture;
11740                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11741                                 continue;
11742                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11743                                 continue;
11744                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11745                 }
11746         }
11747         else
11748         {
11749                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11750                 {
11751                         surfaceindex = surfacelist[surfacelistindex];
11752                         surface = surfaces + surfaceindex;
11753                         // check cull box first because it rejects more than any other check
11754                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11755                                 continue;
11756                         // skip transparent surfaces
11757                         texture = surface->texture;
11758                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11759                                 continue;
11760                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11761                                 continue;
11762                         numtriangles = surface->num_triangles;
11763                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11764                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11765                 }
11766         }
11767 }
11768
11769 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11770 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)
11771 {
11772         int renderentityindex;
11773         float worldmins[3];
11774         float worldmaxs[3];
11775         entity_render_t *ent;
11776
11777         if (!cl_decals_newsystem.integer)
11778                 return;
11779
11780         worldmins[0] = worldorigin[0] - worldsize;
11781         worldmins[1] = worldorigin[1] - worldsize;
11782         worldmins[2] = worldorigin[2] - worldsize;
11783         worldmaxs[0] = worldorigin[0] + worldsize;
11784         worldmaxs[1] = worldorigin[1] + worldsize;
11785         worldmaxs[2] = worldorigin[2] + worldsize;
11786
11787         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11788
11789         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11790         {
11791                 ent = r_refdef.scene.entities[renderentityindex];
11792                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11793                         continue;
11794
11795                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11796         }
11797 }
11798
11799 typedef struct r_decalsystem_splatqueue_s
11800 {
11801         vec3_t worldorigin;
11802         vec3_t worldnormal;
11803         float color[4];
11804         float tcrange[4];
11805         float worldsize;
11806         unsigned int decalsequence;
11807 }
11808 r_decalsystem_splatqueue_t;
11809
11810 int r_decalsystem_numqueued = 0;
11811 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11812
11813 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)
11814 {
11815         r_decalsystem_splatqueue_t *queue;
11816
11817         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11818                 return;
11819
11820         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11821         VectorCopy(worldorigin, queue->worldorigin);
11822         VectorCopy(worldnormal, queue->worldnormal);
11823         Vector4Set(queue->color, r, g, b, a);
11824         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11825         queue->worldsize = worldsize;
11826         queue->decalsequence = cl.decalsequence++;
11827 }
11828
11829 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11830 {
11831         int i;
11832         r_decalsystem_splatqueue_t *queue;
11833
11834         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11835                 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);
11836         r_decalsystem_numqueued = 0;
11837 }
11838
11839 extern cvar_t cl_decals_max;
11840 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11841 {
11842         int i;
11843         decalsystem_t *decalsystem = &ent->decalsystem;
11844         int numdecals;
11845         unsigned int killsequence;
11846         tridecal_t *decal;
11847         float frametime;
11848         float lifetime;
11849
11850         if (!decalsystem->numdecals)
11851                 return;
11852
11853         if (r_showsurfaces.integer)
11854                 return;
11855
11856         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11857         {
11858                 R_DecalSystem_Reset(decalsystem);
11859                 return;
11860         }
11861
11862         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11863         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11864
11865         if (decalsystem->lastupdatetime)
11866                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11867         else
11868                 frametime = 0;
11869         decalsystem->lastupdatetime = r_refdef.scene.time;
11870         numdecals = decalsystem->numdecals;
11871
11872         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11873         {
11874                 if (decal->color4f[0][3])
11875                 {
11876                         decal->lived += frametime;
11877                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11878                         {
11879                                 memset(decal, 0, sizeof(*decal));
11880                                 if (decalsystem->freedecal > i)
11881                                         decalsystem->freedecal = i;
11882                         }
11883                 }
11884         }
11885         decal = decalsystem->decals;
11886         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11887                 numdecals--;
11888
11889         // collapse the array by shuffling the tail decals into the gaps
11890         for (;;)
11891         {
11892                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11893                         decalsystem->freedecal++;
11894                 if (decalsystem->freedecal == numdecals)
11895                         break;
11896                 decal[decalsystem->freedecal] = decal[--numdecals];
11897         }
11898
11899         decalsystem->numdecals = numdecals;
11900
11901         if (numdecals <= 0)
11902         {
11903                 // if there are no decals left, reset decalsystem
11904                 R_DecalSystem_Reset(decalsystem);
11905         }
11906 }
11907
11908 extern skinframe_t *decalskinframe;
11909 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11910 {
11911         int i;
11912         decalsystem_t *decalsystem = &ent->decalsystem;
11913         int numdecals;
11914         tridecal_t *decal;
11915         float faderate;
11916         float alpha;
11917         float *v3f;
11918         float *c4f;
11919         float *t2f;
11920         const int *e;
11921         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11922         int numtris = 0;
11923
11924         numdecals = decalsystem->numdecals;
11925         if (!numdecals)
11926                 return;
11927
11928         if (r_showsurfaces.integer)
11929                 return;
11930
11931         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11932         {
11933                 R_DecalSystem_Reset(decalsystem);
11934                 return;
11935         }
11936
11937         // if the model is static it doesn't matter what value we give for
11938         // wantnormals and wanttangents, so this logic uses only rules applicable
11939         // to a model, knowing that they are meaningless otherwise
11940         RSurf_ActiveModelEntity(ent, false, false, false);
11941
11942         decalsystem->lastupdatetime = r_refdef.scene.time;
11943
11944         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11945
11946         // update vertex positions for animated models
11947         v3f = decalsystem->vertex3f;
11948         c4f = decalsystem->color4f;
11949         t2f = decalsystem->texcoord2f;
11950         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11951         {
11952                 if (!decal->color4f[0][3])
11953                         continue;
11954
11955                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11956                         continue;
11957
11958                 // skip backfaces
11959                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11960                         continue;
11961
11962                 // update color values for fading decals
11963                 if (decal->lived >= cl_decals_time.value)
11964                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11965                 else
11966                         alpha = 1.0f;
11967
11968                 c4f[ 0] = decal->color4f[0][0] * alpha;
11969                 c4f[ 1] = decal->color4f[0][1] * alpha;
11970                 c4f[ 2] = decal->color4f[0][2] * alpha;
11971                 c4f[ 3] = 1;
11972                 c4f[ 4] = decal->color4f[1][0] * alpha;
11973                 c4f[ 5] = decal->color4f[1][1] * alpha;
11974                 c4f[ 6] = decal->color4f[1][2] * alpha;
11975                 c4f[ 7] = 1;
11976                 c4f[ 8] = decal->color4f[2][0] * alpha;
11977                 c4f[ 9] = decal->color4f[2][1] * alpha;
11978                 c4f[10] = decal->color4f[2][2] * alpha;
11979                 c4f[11] = 1;
11980
11981                 t2f[0] = decal->texcoord2f[0][0];
11982                 t2f[1] = decal->texcoord2f[0][1];
11983                 t2f[2] = decal->texcoord2f[1][0];
11984                 t2f[3] = decal->texcoord2f[1][1];
11985                 t2f[4] = decal->texcoord2f[2][0];
11986                 t2f[5] = decal->texcoord2f[2][1];
11987
11988                 // update vertex positions for animated models
11989                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11990                 {
11991                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11992                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11993                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11994                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11995                 }
11996                 else
11997                 {
11998                         VectorCopy(decal->vertex3f[0], v3f);
11999                         VectorCopy(decal->vertex3f[1], v3f + 3);
12000                         VectorCopy(decal->vertex3f[2], v3f + 6);
12001                 }
12002
12003                 if (r_refdef.fogenabled)
12004                 {
12005                         alpha = RSurf_FogVertex(v3f);
12006                         VectorScale(c4f, alpha, c4f);
12007                         alpha = RSurf_FogVertex(v3f + 3);
12008                         VectorScale(c4f + 4, alpha, c4f + 4);
12009                         alpha = RSurf_FogVertex(v3f + 6);
12010                         VectorScale(c4f + 8, alpha, c4f + 8);
12011                 }
12012
12013                 v3f += 9;
12014                 c4f += 12;
12015                 t2f += 6;
12016                 numtris++;
12017         }
12018
12019         if (numtris > 0)
12020         {
12021                 r_refdef.stats[r_stat_drawndecals] += numtris;
12022
12023                 // now render the decals all at once
12024                 // (this assumes they all use one particle font texture!)
12025                 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);
12026 //              R_Mesh_ResetTextureState();
12027                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12028                 GL_DepthMask(false);
12029                 GL_DepthRange(0, 1);
12030                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12031                 GL_DepthTest(true);
12032                 GL_CullFace(GL_NONE);
12033                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12034                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12035                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12036         }
12037 }
12038
12039 static void R_DrawModelDecals(void)
12040 {
12041         int i, numdecals;
12042
12043         // fade faster when there are too many decals
12044         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12045         for (i = 0;i < r_refdef.scene.numentities;i++)
12046                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12047
12048         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12049         for (i = 0;i < r_refdef.scene.numentities;i++)
12050                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12051                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12052
12053         R_DecalSystem_ApplySplatEntitiesQueue();
12054
12055         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12056         for (i = 0;i < r_refdef.scene.numentities;i++)
12057                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12058
12059         r_refdef.stats[r_stat_totaldecals] += numdecals;
12060
12061         if (r_showsurfaces.integer)
12062                 return;
12063
12064         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12065
12066         for (i = 0;i < r_refdef.scene.numentities;i++)
12067         {
12068                 if (!r_refdef.viewcache.entityvisible[i])
12069                         continue;
12070                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12071                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12072         }
12073 }
12074
12075 extern cvar_t mod_collision_bih;
12076 static void R_DrawDebugModel(void)
12077 {
12078         entity_render_t *ent = rsurface.entity;
12079         int i, j, flagsmask;
12080         const msurface_t *surface;
12081         dp_model_t *model = ent->model;
12082
12083         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12084                 return;
12085
12086         if (r_showoverdraw.value > 0)
12087         {
12088                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12089                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12090                 R_SetupShader_Generic_NoTexture(false, false);
12091                 GL_DepthTest(false);
12092                 GL_DepthMask(false);
12093                 GL_DepthRange(0, 1);
12094                 GL_BlendFunc(GL_ONE, GL_ONE);
12095                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12096                 {
12097                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12098                                 continue;
12099                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12100                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12101                         {
12102                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12103                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12104                                 if (!rsurface.texture->currentlayers->depthmask)
12105                                         GL_Color(c, 0, 0, 1.0f);
12106                                 else if (ent == r_refdef.scene.worldentity)
12107                                         GL_Color(c, c, c, 1.0f);
12108                                 else
12109                                         GL_Color(0, c, 0, 1.0f);
12110                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12111                                 RSurf_DrawBatch();
12112                         }
12113                 }
12114                 rsurface.texture = NULL;
12115         }
12116
12117         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12118
12119 //      R_Mesh_ResetTextureState();
12120         R_SetupShader_Generic_NoTexture(false, false);
12121         GL_DepthRange(0, 1);
12122         GL_DepthTest(!r_showdisabledepthtest.integer);
12123         GL_DepthMask(false);
12124         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12125
12126         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12127         {
12128                 int triangleindex;
12129                 int bihleafindex;
12130                 qboolean cullbox = false;
12131                 const q3mbrush_t *brush;
12132                 const bih_t *bih = &model->collision_bih;
12133                 const bih_leaf_t *bihleaf;
12134                 float vertex3f[3][3];
12135                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12136                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12137                 {
12138                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12139                                 continue;
12140                         switch (bihleaf->type)
12141                         {
12142                         case BIH_BRUSH:
12143                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12144                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12145                                 {
12146                                         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);
12147                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12148                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12149                                 }
12150                                 break;
12151                         case BIH_COLLISIONTRIANGLE:
12152                                 triangleindex = bihleaf->itemindex;
12153                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12154                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12155                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12156                                 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);
12157                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12158                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12159                                 break;
12160                         case BIH_RENDERTRIANGLE:
12161                                 triangleindex = bihleaf->itemindex;
12162                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12163                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12164                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12165                                 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);
12166                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12167                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12168                                 break;
12169                         }
12170                 }
12171         }
12172
12173         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12174
12175 #ifndef USE_GLES2
12176         if (r_showtris.integer && qglPolygonMode)
12177         {
12178                 if (r_showdisabledepthtest.integer)
12179                 {
12180                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12181                         GL_DepthMask(false);
12182                 }
12183                 else
12184                 {
12185                         GL_BlendFunc(GL_ONE, GL_ZERO);
12186                         GL_DepthMask(true);
12187                 }
12188                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12189                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12190                 {
12191                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12192                                 continue;
12193                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12194                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12195                         {
12196                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12197                                 if (!rsurface.texture->currentlayers->depthmask)
12198                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12199                                 else if (ent == r_refdef.scene.worldentity)
12200                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12201                                 else
12202                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12203                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12204                                 RSurf_DrawBatch();
12205                         }
12206                 }
12207                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12208                 rsurface.texture = NULL;
12209         }
12210
12211         if (r_shownormals.value != 0 && qglBegin)
12212         {
12213                 int l, k;
12214                 vec3_t v;
12215                 if (r_showdisabledepthtest.integer)
12216                 {
12217                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12218                         GL_DepthMask(false);
12219                 }
12220                 else
12221                 {
12222                         GL_BlendFunc(GL_ONE, GL_ZERO);
12223                         GL_DepthMask(true);
12224                 }
12225                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12226                 {
12227                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12228                                 continue;
12229                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12230                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12231                         {
12232                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12233                                 qglBegin(GL_LINES);
12234                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12235                                 {
12236                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12237                                         {
12238                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12239                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12240                                                 qglVertex3f(v[0], v[1], v[2]);
12241                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12242                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12243                                                 qglVertex3f(v[0], v[1], v[2]);
12244                                         }
12245                                 }
12246                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12247                                 {
12248                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12249                                         {
12250                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12251                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12252                                                 qglVertex3f(v[0], v[1], v[2]);
12253                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12254                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12255                                                 qglVertex3f(v[0], v[1], v[2]);
12256                                         }
12257                                 }
12258                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12259                                 {
12260                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12261                                         {
12262                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12263                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12264                                                 qglVertex3f(v[0], v[1], v[2]);
12265                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12266                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12267                                                 qglVertex3f(v[0], v[1], v[2]);
12268                                         }
12269                                 }
12270                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12271                                 {
12272                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12273                                         {
12274                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12275                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12276                                                 qglVertex3f(v[0], v[1], v[2]);
12277                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12278                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12279                                                 qglVertex3f(v[0], v[1], v[2]);
12280                                         }
12281                                 }
12282                                 qglEnd();
12283                                 CHECKGLERROR
12284                         }
12285                 }
12286                 rsurface.texture = NULL;
12287         }
12288 #endif
12289 }
12290
12291 int r_maxsurfacelist = 0;
12292 const msurface_t **r_surfacelist = NULL;
12293 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12294 {
12295         int i, j, endj, flagsmask;
12296         dp_model_t *model = ent->model;
12297         msurface_t *surfaces;
12298         unsigned char *update;
12299         int numsurfacelist = 0;
12300         if (model == NULL)
12301                 return;
12302
12303         if (r_maxsurfacelist < model->num_surfaces)
12304         {
12305                 r_maxsurfacelist = model->num_surfaces;
12306                 if (r_surfacelist)
12307                         Mem_Free((msurface_t **)r_surfacelist);
12308                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12309         }
12310
12311         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12312                 RSurf_ActiveModelEntity(ent, false, false, false);
12313         else if (prepass)
12314                 RSurf_ActiveModelEntity(ent, true, true, true);
12315         else if (depthonly)
12316         {
12317                 switch (vid.renderpath)
12318                 {
12319                 case RENDERPATH_GL20:
12320                 case RENDERPATH_D3D9:
12321                 case RENDERPATH_D3D10:
12322                 case RENDERPATH_D3D11:
12323                 case RENDERPATH_SOFT:
12324                 case RENDERPATH_GLES2:
12325                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12326                         break;
12327                 case RENDERPATH_GL11:
12328                 case RENDERPATH_GL13:
12329                 case RENDERPATH_GLES1:
12330                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12331                         break;
12332                 }
12333         }
12334         else
12335         {
12336                 switch (vid.renderpath)
12337                 {
12338                 case RENDERPATH_GL20:
12339                 case RENDERPATH_D3D9:
12340                 case RENDERPATH_D3D10:
12341                 case RENDERPATH_D3D11:
12342                 case RENDERPATH_SOFT:
12343                 case RENDERPATH_GLES2:
12344                         RSurf_ActiveModelEntity(ent, true, true, false);
12345                         break;
12346                 case RENDERPATH_GL11:
12347                 case RENDERPATH_GL13:
12348                 case RENDERPATH_GLES1:
12349                         RSurf_ActiveModelEntity(ent, true, false, false);
12350                         break;
12351                 }
12352         }
12353
12354         surfaces = model->data_surfaces;
12355         update = model->brushq1.lightmapupdateflags;
12356
12357         // update light styles
12358         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12359         {
12360                 model_brush_lightstyleinfo_t *style;
12361                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12362                 {
12363                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12364                         {
12365                                 int *list = style->surfacelist;
12366                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12367                                 for (j = 0;j < style->numsurfaces;j++)
12368                                         update[list[j]] = true;
12369                         }
12370                 }
12371         }
12372
12373         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12374
12375         if (debug)
12376         {
12377                 R_DrawDebugModel();
12378                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12379                 return;
12380         }
12381
12382         rsurface.lightmaptexture = NULL;
12383         rsurface.deluxemaptexture = NULL;
12384         rsurface.uselightmaptexture = false;
12385         rsurface.texture = NULL;
12386         rsurface.rtlight = NULL;
12387         numsurfacelist = 0;
12388         // add visible surfaces to draw list
12389         if (ent == r_refdef.scene.worldentity)
12390         {
12391                 // for the world entity, check surfacevisible
12392                 for (i = 0;i < model->nummodelsurfaces;i++)
12393                 {
12394                         j = model->sortedmodelsurfaces[i];
12395                         if (r_refdef.viewcache.world_surfacevisible[j])
12396                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12397                 }
12398         }
12399         else
12400         {
12401                 // add all surfaces
12402                 for (i = 0; i < model->nummodelsurfaces; i++)
12403                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12404         }
12405         // don't do anything if there were no surfaces
12406         if (!numsurfacelist)
12407         {
12408                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12409                 return;
12410         }
12411         // update lightmaps if needed
12412         if (update)
12413         {
12414                 int updated = 0;
12415                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12416                 {
12417                         if (update[j])
12418                         {
12419                                 updated++;
12420                                 R_BuildLightMap(ent, surfaces + j);
12421                         }
12422                 }
12423         }
12424
12425         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12426
12427         // add to stats if desired
12428         if (r_speeds.integer && !skysurfaces && !depthonly)
12429         {
12430                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12431                 for (j = 0;j < numsurfacelist;j++)
12432                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12433         }
12434
12435         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12436 }
12437
12438 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12439 {
12440         int q;
12441         static texture_t texture;
12442         static msurface_t surface;
12443         const msurface_t *surfacelist = &surface;
12444
12445         // fake enough texture and surface state to render this geometry
12446
12447         texture.update_lastrenderframe = -1; // regenerate this texture
12448         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12449         texture.basealpha = 1.0f;
12450         texture.currentskinframe = skinframe;
12451         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12452         texture.offsetmapping = OFFSETMAPPING_OFF;
12453         texture.offsetscale = 1;
12454         texture.specularscalemod = 1;
12455         texture.specularpowermod = 1;
12456         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12457
12458         R_DrawCustomSurface_Texture(&texture, texmatrix, materialflags, firstvertex, numvertices, firsttriangle, numtriangles, writedepth, prepass);
12459 }
12460
12461 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)
12462 {
12463         static msurface_t surface;
12464         const msurface_t *surfacelist = &surface;
12465
12466         // fake enough texture and surface state to render this geometry
12467         surface.texture = texture;
12468         surface.num_triangles = numtriangles;
12469         surface.num_firsttriangle = firsttriangle;
12470         surface.num_vertices = numvertices;
12471         surface.num_firstvertex = firstvertex;
12472
12473         // now render it
12474         rsurface.texture = R_GetCurrentTexture(surface.texture);
12475         rsurface.lightmaptexture = NULL;
12476         rsurface.deluxemaptexture = NULL;
12477         rsurface.uselightmaptexture = false;
12478         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12479 }