]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Remove v_glslgamma cvar (now assumed to be 1) and corresponding code like R_DrawGamma.
[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         rsurface.skeleton = NULL;
8680         rsurface.ent_skinnum = 0;
8681         rsurface.ent_qwskin = -1;
8682         rsurface.ent_flags = entflags;
8683         rsurface.shadertime = r_refdef.scene.time - shadertime;
8684         rsurface.modelnumvertices = numvertices;
8685         rsurface.modelnumtriangles = numtriangles;
8686         rsurface.matrix = *matrix;
8687         rsurface.inversematrix = *inversematrix;
8688         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8689         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8690         R_EntityMatrix(&rsurface.matrix);
8691         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8692         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8693         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8694         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8695         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8696         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8697         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8698         rsurface.frameblend[0].lerp = 1;
8699         rsurface.ent_alttextures = false;
8700         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8701         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8702         rsurface.entityskeletaltransform3x4 = NULL;
8703         rsurface.entityskeletaltransform3x4buffer = NULL;
8704         rsurface.entityskeletaltransform3x4offset = 0;
8705         rsurface.entityskeletaltransform3x4size = 0;
8706         rsurface.entityskeletalnumtransforms = 0;
8707         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8708         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8709         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8710         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8711         if (wanttangents)
8712         {
8713                 rsurface.modelvertex3f = (float *)vertex3f;
8714                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8715                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8716                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8717         }
8718         else if (wantnormals)
8719         {
8720                 rsurface.modelvertex3f = (float *)vertex3f;
8721                 rsurface.modelsvector3f = NULL;
8722                 rsurface.modeltvector3f = NULL;
8723                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8724         }
8725         else
8726         {
8727                 rsurface.modelvertex3f = (float *)vertex3f;
8728                 rsurface.modelsvector3f = NULL;
8729                 rsurface.modeltvector3f = NULL;
8730                 rsurface.modelnormal3f = NULL;
8731         }
8732         rsurface.modelvertexmesh = NULL;
8733         rsurface.modelvertexmesh_vertexbuffer = NULL;
8734         rsurface.modelvertexmesh_bufferoffset = 0;
8735         rsurface.modelvertex3f_vertexbuffer = 0;
8736         rsurface.modelvertex3f_bufferoffset = 0;
8737         rsurface.modelsvector3f_vertexbuffer = 0;
8738         rsurface.modelsvector3f_bufferoffset = 0;
8739         rsurface.modeltvector3f_vertexbuffer = 0;
8740         rsurface.modeltvector3f_bufferoffset = 0;
8741         rsurface.modelnormal3f_vertexbuffer = 0;
8742         rsurface.modelnormal3f_bufferoffset = 0;
8743         rsurface.modelgeneratedvertex = true;
8744         rsurface.modellightmapcolor4f  = (float *)color4f;
8745         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8746         rsurface.modellightmapcolor4f_bufferoffset = 0;
8747         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8748         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8749         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8750         rsurface.modeltexcoordlightmap2f  = NULL;
8751         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8752         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8753         rsurface.modelskeletalindex4ub = NULL;
8754         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8755         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8756         rsurface.modelskeletalweight4ub = NULL;
8757         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8758         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8759         rsurface.modelelement3i = (int *)element3i;
8760         rsurface.modelelement3i_indexbuffer = NULL;
8761         rsurface.modelelement3i_bufferoffset = 0;
8762         rsurface.modelelement3s = (unsigned short *)element3s;
8763         rsurface.modelelement3s_indexbuffer = NULL;
8764         rsurface.modelelement3s_bufferoffset = 0;
8765         rsurface.modellightmapoffsets = NULL;
8766         rsurface.modelsurfaces = NULL;
8767         rsurface.batchgeneratedvertex = false;
8768         rsurface.batchfirstvertex = 0;
8769         rsurface.batchnumvertices = 0;
8770         rsurface.batchfirsttriangle = 0;
8771         rsurface.batchnumtriangles = 0;
8772         rsurface.batchvertex3f  = NULL;
8773         rsurface.batchvertex3f_vertexbuffer = NULL;
8774         rsurface.batchvertex3f_bufferoffset = 0;
8775         rsurface.batchsvector3f = NULL;
8776         rsurface.batchsvector3f_vertexbuffer = NULL;
8777         rsurface.batchsvector3f_bufferoffset = 0;
8778         rsurface.batchtvector3f = NULL;
8779         rsurface.batchtvector3f_vertexbuffer = NULL;
8780         rsurface.batchtvector3f_bufferoffset = 0;
8781         rsurface.batchnormal3f  = NULL;
8782         rsurface.batchnormal3f_vertexbuffer = NULL;
8783         rsurface.batchnormal3f_bufferoffset = 0;
8784         rsurface.batchlightmapcolor4f = NULL;
8785         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8786         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8787         rsurface.batchtexcoordtexture2f = NULL;
8788         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8789         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8790         rsurface.batchtexcoordlightmap2f = NULL;
8791         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8792         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8793         rsurface.batchskeletalindex4ub = NULL;
8794         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8795         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8796         rsurface.batchskeletalweight4ub = NULL;
8797         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8798         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8799         rsurface.batchvertexmesh = NULL;
8800         rsurface.batchvertexmesh_vertexbuffer = NULL;
8801         rsurface.batchvertexmesh_bufferoffset = 0;
8802         rsurface.batchelement3i = NULL;
8803         rsurface.batchelement3i_indexbuffer = NULL;
8804         rsurface.batchelement3i_bufferoffset = 0;
8805         rsurface.batchelement3s = NULL;
8806         rsurface.batchelement3s_indexbuffer = NULL;
8807         rsurface.batchelement3s_bufferoffset = 0;
8808         rsurface.passcolor4f = NULL;
8809         rsurface.passcolor4f_vertexbuffer = NULL;
8810         rsurface.passcolor4f_bufferoffset = 0;
8811         rsurface.forcecurrenttextureupdate = true;
8812
8813         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8814         {
8815                 if ((wantnormals || wanttangents) && !normal3f)
8816                 {
8817                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8818                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8819                 }
8820                 if (wanttangents && !svector3f)
8821                 {
8822                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8823                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8824                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8825                 }
8826         }
8827 }
8828
8829 float RSurf_FogPoint(const float *v)
8830 {
8831         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8832         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8833         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8834         float FogHeightFade = r_refdef.fogheightfade;
8835         float fogfrac;
8836         unsigned int fogmasktableindex;
8837         if (r_refdef.fogplaneviewabove)
8838                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8839         else
8840                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8841         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8842         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8843 }
8844
8845 float RSurf_FogVertex(const float *v)
8846 {
8847         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8848         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8849         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8850         float FogHeightFade = rsurface.fogheightfade;
8851         float fogfrac;
8852         unsigned int fogmasktableindex;
8853         if (r_refdef.fogplaneviewabove)
8854                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8855         else
8856                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8857         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8858         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8859 }
8860
8861 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8862 {
8863         int i;
8864         for (i = 0;i < numelements;i++)
8865                 outelement3i[i] = inelement3i[i] + adjust;
8866 }
8867
8868 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8869 extern cvar_t gl_vbo;
8870 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8871 {
8872         int deformindex;
8873         int firsttriangle;
8874         int numtriangles;
8875         int firstvertex;
8876         int endvertex;
8877         int numvertices;
8878         int surfacefirsttriangle;
8879         int surfacenumtriangles;
8880         int surfacefirstvertex;
8881         int surfaceendvertex;
8882         int surfacenumvertices;
8883         int batchnumsurfaces = texturenumsurfaces;
8884         int batchnumvertices;
8885         int batchnumtriangles;
8886         int needsupdate;
8887         int i, j;
8888         qboolean gaps;
8889         qboolean dynamicvertex;
8890         float amplitude;
8891         float animpos;
8892         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8893         float waveparms[4];
8894         unsigned char *ub;
8895         q3shaderinfo_deform_t *deform;
8896         const msurface_t *surface, *firstsurface;
8897         r_vertexmesh_t *vertexmesh;
8898         if (!texturenumsurfaces)
8899                 return;
8900         // find vertex range of this surface batch
8901         gaps = false;
8902         firstsurface = texturesurfacelist[0];
8903         firsttriangle = firstsurface->num_firsttriangle;
8904         batchnumvertices = 0;
8905         batchnumtriangles = 0;
8906         firstvertex = endvertex = firstsurface->num_firstvertex;
8907         for (i = 0;i < texturenumsurfaces;i++)
8908         {
8909                 surface = texturesurfacelist[i];
8910                 if (surface != firstsurface + i)
8911                         gaps = true;
8912                 surfacefirstvertex = surface->num_firstvertex;
8913                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8914                 surfacenumvertices = surface->num_vertices;
8915                 surfacenumtriangles = surface->num_triangles;
8916                 if (firstvertex > surfacefirstvertex)
8917                         firstvertex = surfacefirstvertex;
8918                 if (endvertex < surfaceendvertex)
8919                         endvertex = surfaceendvertex;
8920                 batchnumvertices += surfacenumvertices;
8921                 batchnumtriangles += surfacenumtriangles;
8922         }
8923
8924         r_refdef.stats[r_stat_batch_batches]++;
8925         if (gaps)
8926                 r_refdef.stats[r_stat_batch_withgaps]++;
8927         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8928         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8929         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8930
8931         // we now know the vertex range used, and if there are any gaps in it
8932         rsurface.batchfirstvertex = firstvertex;
8933         rsurface.batchnumvertices = endvertex - firstvertex;
8934         rsurface.batchfirsttriangle = firsttriangle;
8935         rsurface.batchnumtriangles = batchnumtriangles;
8936
8937         // this variable holds flags for which properties have been updated that
8938         // may require regenerating vertexmesh array...
8939         needsupdate = 0;
8940
8941         // check if any dynamic vertex processing must occur
8942         dynamicvertex = false;
8943
8944         // a cvar to force the dynamic vertex path to be taken, for debugging
8945         if (r_batch_debugdynamicvertexpath.integer)
8946         {
8947                 if (!dynamicvertex)
8948                 {
8949                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8950                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8951                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8952                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8953                 }
8954                 dynamicvertex = true;
8955         }
8956
8957         // if there is a chance of animated vertex colors, it's a dynamic batch
8958         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8959         {
8960                 if (!dynamicvertex)
8961                 {
8962                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8963                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8964                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8965                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8966                 }
8967                 dynamicvertex = true;
8968                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8969         }
8970
8971         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8972         {
8973                 switch (deform->deform)
8974                 {
8975                 default:
8976                 case Q3DEFORM_PROJECTIONSHADOW:
8977                 case Q3DEFORM_TEXT0:
8978                 case Q3DEFORM_TEXT1:
8979                 case Q3DEFORM_TEXT2:
8980                 case Q3DEFORM_TEXT3:
8981                 case Q3DEFORM_TEXT4:
8982                 case Q3DEFORM_TEXT5:
8983                 case Q3DEFORM_TEXT6:
8984                 case Q3DEFORM_TEXT7:
8985                 case Q3DEFORM_NONE:
8986                         break;
8987                 case Q3DEFORM_AUTOSPRITE:
8988                         if (!dynamicvertex)
8989                         {
8990                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8991                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8992                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8993                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8994                         }
8995                         dynamicvertex = true;
8996                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8997                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8998                         break;
8999                 case Q3DEFORM_AUTOSPRITE2:
9000                         if (!dynamicvertex)
9001                         {
9002                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9003                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9004                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9005                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9006                         }
9007                         dynamicvertex = true;
9008                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9009                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9010                         break;
9011                 case Q3DEFORM_NORMAL:
9012                         if (!dynamicvertex)
9013                         {
9014                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9015                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9016                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9017                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9018                         }
9019                         dynamicvertex = true;
9020                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9021                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9022                         break;
9023                 case Q3DEFORM_WAVE:
9024                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9025                                 break; // if wavefunc is a nop, ignore this transform
9026                         if (!dynamicvertex)
9027                         {
9028                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9029                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9030                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9031                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9032                         }
9033                         dynamicvertex = true;
9034                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9035                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9036                         break;
9037                 case Q3DEFORM_BULGE:
9038                         if (!dynamicvertex)
9039                         {
9040                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9041                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9042                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9043                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9044                         }
9045                         dynamicvertex = true;
9046                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9047                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9048                         break;
9049                 case Q3DEFORM_MOVE:
9050                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9051                                 break; // if wavefunc is a nop, ignore this transform
9052                         if (!dynamicvertex)
9053                         {
9054                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9055                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9056                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9057                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9058                         }
9059                         dynamicvertex = true;
9060                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9061                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9062                         break;
9063                 }
9064         }
9065         if (rsurface.texture->materialshaderpass)
9066         {
9067                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9068                 {
9069                 default:
9070                 case Q3TCGEN_TEXTURE:
9071                         break;
9072                 case Q3TCGEN_LIGHTMAP:
9073                         if (!dynamicvertex)
9074                         {
9075                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9076                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9077                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9078                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9079                         }
9080                         dynamicvertex = true;
9081                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9082                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9083                         break;
9084                 case Q3TCGEN_VECTOR:
9085                         if (!dynamicvertex)
9086                         {
9087                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9088                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9089                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9090                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9091                         }
9092                         dynamicvertex = true;
9093                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9094                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9095                         break;
9096                 case Q3TCGEN_ENVIRONMENT:
9097                         if (!dynamicvertex)
9098                         {
9099                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9100                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9101                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9102                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9103                         }
9104                         dynamicvertex = true;
9105                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9106                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9107                         break;
9108                 }
9109                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9110                 {
9111                         if (!dynamicvertex)
9112                         {
9113                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9114                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9115                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9116                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9117                         }
9118                         dynamicvertex = true;
9119                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9120                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9121                 }
9122         }
9123
9124         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9125         {
9126                 if (!dynamicvertex)
9127                 {
9128                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9129                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9130                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9131                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9132                 }
9133                 dynamicvertex = true;
9134                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9135         }
9136
9137         // when the model data has no vertex buffer (dynamic mesh), we need to
9138         // eliminate gaps
9139         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9140                 batchneed |= BATCHNEED_NOGAPS;
9141
9142         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9143         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9144         // we ensure this by treating the vertex batch as dynamic...
9145         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9146         {
9147                 if (!dynamicvertex)
9148                 {
9149                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9150                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9151                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9152                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9153                 }
9154                 dynamicvertex = true;
9155         }
9156
9157         if (dynamicvertex)
9158         {
9159                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9160                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9161                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9162                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9163                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9164                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9165                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9166                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9167         }
9168
9169         // if needsupdate, we have to do a dynamic vertex batch for sure
9170         if (needsupdate & batchneed)
9171         {
9172                 if (!dynamicvertex)
9173                 {
9174                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9175                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9176                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9177                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9178                 }
9179                 dynamicvertex = true;
9180         }
9181
9182         // see if we need to build vertexmesh from arrays
9183         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9184         {
9185                 if (!dynamicvertex)
9186                 {
9187                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9188                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9189                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9190                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9191                 }
9192                 dynamicvertex = true;
9193         }
9194
9195         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9196         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9197                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9198
9199         rsurface.batchvertex3f = rsurface.modelvertex3f;
9200         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9201         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9202         rsurface.batchsvector3f = rsurface.modelsvector3f;
9203         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9204         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9205         rsurface.batchtvector3f = rsurface.modeltvector3f;
9206         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9207         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9208         rsurface.batchnormal3f = rsurface.modelnormal3f;
9209         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9210         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9211         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9212         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9213         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9214         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9215         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9216         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9217         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9218         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9219         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9220         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9221         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9222         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9223         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9224         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9225         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9226         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9227         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9228         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9229         rsurface.batchelement3i = rsurface.modelelement3i;
9230         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9231         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9232         rsurface.batchelement3s = rsurface.modelelement3s;
9233         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9234         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9235         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9236         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9237         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9238         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9239         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9240
9241         // if any dynamic vertex processing has to occur in software, we copy the
9242         // entire surface list together before processing to rebase the vertices
9243         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9244         //
9245         // if any gaps exist and we do not have a static vertex buffer, we have to
9246         // copy the surface list together to avoid wasting upload bandwidth on the
9247         // vertices in the gaps.
9248         //
9249         // if gaps exist and we have a static vertex buffer, we can choose whether
9250         // to combine the index buffer ranges into one dynamic index buffer or
9251         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9252         //
9253         // in many cases the batch is reduced to one draw call.
9254
9255         rsurface.batchmultidraw = false;
9256         rsurface.batchmultidrawnumsurfaces = 0;
9257         rsurface.batchmultidrawsurfacelist = NULL;
9258
9259         if (!dynamicvertex)
9260         {
9261                 // static vertex data, just set pointers...
9262                 rsurface.batchgeneratedvertex = false;
9263                 // if there are gaps, we want to build a combined index buffer,
9264                 // otherwise use the original static buffer with an appropriate offset
9265                 if (gaps)
9266                 {
9267                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9268                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9269                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9270                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9271                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9272                         {
9273                                 rsurface.batchmultidraw = true;
9274                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9275                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9276                                 return;
9277                         }
9278                         // build a new triangle elements array for this batch
9279                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9280                         rsurface.batchfirsttriangle = 0;
9281                         numtriangles = 0;
9282                         for (i = 0;i < texturenumsurfaces;i++)
9283                         {
9284                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9285                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9286                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9287                                 numtriangles += surfacenumtriangles;
9288                         }
9289                         rsurface.batchelement3i_indexbuffer = NULL;
9290                         rsurface.batchelement3i_bufferoffset = 0;
9291                         rsurface.batchelement3s = NULL;
9292                         rsurface.batchelement3s_indexbuffer = NULL;
9293                         rsurface.batchelement3s_bufferoffset = 0;
9294                         if (endvertex <= 65536)
9295                         {
9296                                 // make a 16bit (unsigned short) index array if possible
9297                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9298                                 for (i = 0;i < numtriangles*3;i++)
9299                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9300                         }
9301                         // upload buffer data for the copytriangles batch
9302                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9303                         {
9304                                 if (rsurface.batchelement3s)
9305                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9306                                 else if (rsurface.batchelement3i)
9307                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9308                         }
9309                 }
9310                 else
9311                 {
9312                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9313                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9314                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9315                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9316                 }
9317                 return;
9318         }
9319
9320         // something needs software processing, do it for real...
9321         // we only directly handle separate array data in this case and then
9322         // generate interleaved data if needed...
9323         rsurface.batchgeneratedvertex = true;
9324         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9325         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9326         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9327         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9328
9329         // now copy the vertex data into a combined array and make an index array
9330         // (this is what Quake3 does all the time)
9331         // we also apply any skeletal animation here that would have been done in
9332         // the vertex shader, because most of the dynamic vertex animation cases
9333         // need actual vertex positions and normals
9334         //if (dynamicvertex)
9335         {
9336                 rsurface.batchvertexmesh = NULL;
9337                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9338                 rsurface.batchvertexmesh_bufferoffset = 0;
9339                 rsurface.batchvertex3f = NULL;
9340                 rsurface.batchvertex3f_vertexbuffer = NULL;
9341                 rsurface.batchvertex3f_bufferoffset = 0;
9342                 rsurface.batchsvector3f = NULL;
9343                 rsurface.batchsvector3f_vertexbuffer = NULL;
9344                 rsurface.batchsvector3f_bufferoffset = 0;
9345                 rsurface.batchtvector3f = NULL;
9346                 rsurface.batchtvector3f_vertexbuffer = NULL;
9347                 rsurface.batchtvector3f_bufferoffset = 0;
9348                 rsurface.batchnormal3f = NULL;
9349                 rsurface.batchnormal3f_vertexbuffer = NULL;
9350                 rsurface.batchnormal3f_bufferoffset = 0;
9351                 rsurface.batchlightmapcolor4f = NULL;
9352                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9353                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9354                 rsurface.batchtexcoordtexture2f = NULL;
9355                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9356                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9357                 rsurface.batchtexcoordlightmap2f = NULL;
9358                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9359                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9360                 rsurface.batchskeletalindex4ub = NULL;
9361                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9362                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9363                 rsurface.batchskeletalweight4ub = NULL;
9364                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9365                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9366                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9367                 rsurface.batchelement3i_indexbuffer = NULL;
9368                 rsurface.batchelement3i_bufferoffset = 0;
9369                 rsurface.batchelement3s = NULL;
9370                 rsurface.batchelement3s_indexbuffer = NULL;
9371                 rsurface.batchelement3s_bufferoffset = 0;
9372                 rsurface.batchskeletaltransform3x4buffer = NULL;
9373                 rsurface.batchskeletaltransform3x4offset = 0;
9374                 rsurface.batchskeletaltransform3x4size = 0;
9375                 // we'll only be setting up certain arrays as needed
9376                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9377                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9378                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9379                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9380                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9381                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9382                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9383                 {
9384                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9385                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9386                 }
9387                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9388                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9389                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9390                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9391                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9392                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9393                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9394                 {
9395                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9396                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9397                 }
9398                 numvertices = 0;
9399                 numtriangles = 0;
9400                 for (i = 0;i < texturenumsurfaces;i++)
9401                 {
9402                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9403                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9404                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9405                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9406                         // copy only the data requested
9407                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9408                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9409                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9410                         {
9411                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9412                                 {
9413                                         if (rsurface.batchvertex3f)
9414                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9415                                         else
9416                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9417                                 }
9418                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9419                                 {
9420                                         if (rsurface.modelnormal3f)
9421                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9422                                         else
9423                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9424                                 }
9425                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9426                                 {
9427                                         if (rsurface.modelsvector3f)
9428                                         {
9429                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9430                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9431                                         }
9432                                         else
9433                                         {
9434                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9435                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9436                                         }
9437                                 }
9438                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9439                                 {
9440                                         if (rsurface.modellightmapcolor4f)
9441                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9442                                         else
9443                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9444                                 }
9445                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9446                                 {
9447                                         if (rsurface.modeltexcoordtexture2f)
9448                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9449                                         else
9450                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9451                                 }
9452                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9453                                 {
9454                                         if (rsurface.modeltexcoordlightmap2f)
9455                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9456                                         else
9457                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9458                                 }
9459                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9460                                 {
9461                                         if (rsurface.modelskeletalindex4ub)
9462                                         {
9463                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9464                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9465                                         }
9466                                         else
9467                                         {
9468                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9469                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9470                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9471                                                 for (j = 0;j < surfacenumvertices;j++)
9472                                                         ub[j*4] = 255;
9473                                         }
9474                                 }
9475                         }
9476                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9477                         numvertices += surfacenumvertices;
9478                         numtriangles += surfacenumtriangles;
9479                 }
9480
9481                 // generate a 16bit index array as well if possible
9482                 // (in general, dynamic batches fit)
9483                 if (numvertices <= 65536)
9484                 {
9485                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9486                         for (i = 0;i < numtriangles*3;i++)
9487                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9488                 }
9489
9490                 // since we've copied everything, the batch now starts at 0
9491                 rsurface.batchfirstvertex = 0;
9492                 rsurface.batchnumvertices = batchnumvertices;
9493                 rsurface.batchfirsttriangle = 0;
9494                 rsurface.batchnumtriangles = batchnumtriangles;
9495         }
9496
9497         // apply skeletal animation that would have been done in the vertex shader
9498         if (rsurface.batchskeletaltransform3x4)
9499         {
9500                 const unsigned char *si;
9501                 const unsigned char *sw;
9502                 const float *t[4];
9503                 const float *b = rsurface.batchskeletaltransform3x4;
9504                 float *vp, *vs, *vt, *vn;
9505                 float w[4];
9506                 float m[3][4], n[3][4];
9507                 float tp[3], ts[3], tt[3], tn[3];
9508                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9509                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9510                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9511                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9512                 si = rsurface.batchskeletalindex4ub;
9513                 sw = rsurface.batchskeletalweight4ub;
9514                 vp = rsurface.batchvertex3f;
9515                 vs = rsurface.batchsvector3f;
9516                 vt = rsurface.batchtvector3f;
9517                 vn = rsurface.batchnormal3f;
9518                 memset(m[0], 0, sizeof(m));
9519                 memset(n[0], 0, sizeof(n));
9520                 for (i = 0;i < batchnumvertices;i++)
9521                 {
9522                         t[0] = b + si[0]*12;
9523                         if (sw[0] == 255)
9524                         {
9525                                 // common case - only one matrix
9526                                 m[0][0] = t[0][ 0];
9527                                 m[0][1] = t[0][ 1];
9528                                 m[0][2] = t[0][ 2];
9529                                 m[0][3] = t[0][ 3];
9530                                 m[1][0] = t[0][ 4];
9531                                 m[1][1] = t[0][ 5];
9532                                 m[1][2] = t[0][ 6];
9533                                 m[1][3] = t[0][ 7];
9534                                 m[2][0] = t[0][ 8];
9535                                 m[2][1] = t[0][ 9];
9536                                 m[2][2] = t[0][10];
9537                                 m[2][3] = t[0][11];
9538                         }
9539                         else if (sw[2] + sw[3])
9540                         {
9541                                 // blend 4 matrices
9542                                 t[1] = b + si[1]*12;
9543                                 t[2] = b + si[2]*12;
9544                                 t[3] = b + si[3]*12;
9545                                 w[0] = sw[0] * (1.0f / 255.0f);
9546                                 w[1] = sw[1] * (1.0f / 255.0f);
9547                                 w[2] = sw[2] * (1.0f / 255.0f);
9548                                 w[3] = sw[3] * (1.0f / 255.0f);
9549                                 // blend the matrices
9550                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9551                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9552                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9553                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9554                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9555                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9556                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9557                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9558                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9559                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9560                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9561                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9562                         }
9563                         else
9564                         {
9565                                 // blend 2 matrices
9566                                 t[1] = b + si[1]*12;
9567                                 w[0] = sw[0] * (1.0f / 255.0f);
9568                                 w[1] = sw[1] * (1.0f / 255.0f);
9569                                 // blend the matrices
9570                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9571                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9572                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9573                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9574                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9575                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9576                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9577                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9578                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9579                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9580                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9581                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9582                         }
9583                         si += 4;
9584                         sw += 4;
9585                         // modify the vertex
9586                         VectorCopy(vp, tp);
9587                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9588                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9589                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9590                         vp += 3;
9591                         if (vn)
9592                         {
9593                                 // the normal transformation matrix is a set of cross products...
9594                                 CrossProduct(m[1], m[2], n[0]);
9595                                 CrossProduct(m[2], m[0], n[1]);
9596                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9597                                 VectorCopy(vn, tn);
9598                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9599                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9600                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9601                                 VectorNormalize(vn);
9602                                 vn += 3;
9603                                 if (vs)
9604                                 {
9605                                         VectorCopy(vs, ts);
9606                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9607                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9608                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9609                                         VectorNormalize(vs);
9610                                         vs += 3;
9611                                         VectorCopy(vt, tt);
9612                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9613                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9614                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9615                                         VectorNormalize(vt);
9616                                         vt += 3;
9617                                 }
9618                         }
9619                 }
9620                 rsurface.batchskeletaltransform3x4 = NULL;
9621                 rsurface.batchskeletalnumtransforms = 0;
9622         }
9623
9624         // q1bsp surfaces rendered in vertex color mode have to have colors
9625         // calculated based on lightstyles
9626         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9627         {
9628                 // generate color arrays for the surfaces in this list
9629                 int c[4];
9630                 int scale;
9631                 int size3;
9632                 const int *offsets;
9633                 const unsigned char *lm;
9634                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9635                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9636                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9637                 numvertices = 0;
9638                 for (i = 0;i < texturenumsurfaces;i++)
9639                 {
9640                         surface = texturesurfacelist[i];
9641                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9642                         surfacenumvertices = surface->num_vertices;
9643                         if (surface->lightmapinfo->samples)
9644                         {
9645                                 for (j = 0;j < surfacenumvertices;j++)
9646                                 {
9647                                         lm = surface->lightmapinfo->samples + offsets[j];
9648                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9649                                         VectorScale(lm, scale, c);
9650                                         if (surface->lightmapinfo->styles[1] != 255)
9651                                         {
9652                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9653                                                 lm += size3;
9654                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9655                                                 VectorMA(c, scale, lm, c);
9656                                                 if (surface->lightmapinfo->styles[2] != 255)
9657                                                 {
9658                                                         lm += size3;
9659                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9660                                                         VectorMA(c, scale, lm, c);
9661                                                         if (surface->lightmapinfo->styles[3] != 255)
9662                                                         {
9663                                                                 lm += size3;
9664                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9665                                                                 VectorMA(c, scale, lm, c);
9666                                                         }
9667                                                 }
9668                                         }
9669                                         c[0] >>= 7;
9670                                         c[1] >>= 7;
9671                                         c[2] >>= 7;
9672                                         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);
9673                                         numvertices++;
9674                                 }
9675                         }
9676                         else
9677                         {
9678                                 for (j = 0;j < surfacenumvertices;j++)
9679                                 {
9680                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9681                                         numvertices++;
9682                                 }
9683                         }
9684                 }
9685         }
9686
9687         // if vertices are deformed (sprite flares and things in maps, possibly
9688         // water waves, bulges and other deformations), modify the copied vertices
9689         // in place
9690         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9691         {
9692                 float scale;
9693                 switch (deform->deform)
9694                 {
9695                 default:
9696                 case Q3DEFORM_PROJECTIONSHADOW:
9697                 case Q3DEFORM_TEXT0:
9698                 case Q3DEFORM_TEXT1:
9699                 case Q3DEFORM_TEXT2:
9700                 case Q3DEFORM_TEXT3:
9701                 case Q3DEFORM_TEXT4:
9702                 case Q3DEFORM_TEXT5:
9703                 case Q3DEFORM_TEXT6:
9704                 case Q3DEFORM_TEXT7:
9705                 case Q3DEFORM_NONE:
9706                         break;
9707                 case Q3DEFORM_AUTOSPRITE:
9708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9709                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9710                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9711                         VectorNormalize(newforward);
9712                         VectorNormalize(newright);
9713                         VectorNormalize(newup);
9714 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9715 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9716 //                      rsurface.batchvertex3f_bufferoffset = 0;
9717 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9718 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9719 //                      rsurface.batchsvector3f_bufferoffset = 0;
9720 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9721 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9722 //                      rsurface.batchtvector3f_bufferoffset = 0;
9723 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9724 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9725 //                      rsurface.batchnormal3f_bufferoffset = 0;
9726                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9727                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9728                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9729                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9730                                 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);
9731                         // a single autosprite surface can contain multiple sprites...
9732                         for (j = 0;j < batchnumvertices - 3;j += 4)
9733                         {
9734                                 VectorClear(center);
9735                                 for (i = 0;i < 4;i++)
9736                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9737                                 VectorScale(center, 0.25f, center);
9738                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9739                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9740                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9741                                 for (i = 0;i < 4;i++)
9742                                 {
9743                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9744                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9745                                 }
9746                         }
9747                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9748                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9749                         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);
9750                         break;
9751                 case Q3DEFORM_AUTOSPRITE2:
9752                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9753                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9754                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9755                         VectorNormalize(newforward);
9756                         VectorNormalize(newright);
9757                         VectorNormalize(newup);
9758 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9759 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9760 //                      rsurface.batchvertex3f_bufferoffset = 0;
9761                         {
9762                                 const float *v1, *v2;
9763                                 vec3_t start, end;
9764                                 float f, l;
9765                                 struct
9766                                 {
9767                                         float length2;
9768                                         const float *v1;
9769                                         const float *v2;
9770                                 }
9771                                 shortest[2];
9772                                 memset(shortest, 0, sizeof(shortest));
9773                                 // a single autosprite surface can contain multiple sprites...
9774                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9775                                 {
9776                                         VectorClear(center);
9777                                         for (i = 0;i < 4;i++)
9778                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9779                                         VectorScale(center, 0.25f, center);
9780                                         // find the two shortest edges, then use them to define the
9781                                         // axis vectors for rotating around the central axis
9782                                         for (i = 0;i < 6;i++)
9783                                         {
9784                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9785                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9786                                                 l = VectorDistance2(v1, v2);
9787                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9788                                                 if (v1[2] != v2[2])
9789                                                         l += (1.0f / 1024.0f);
9790                                                 if (shortest[0].length2 > l || i == 0)
9791                                                 {
9792                                                         shortest[1] = shortest[0];
9793                                                         shortest[0].length2 = l;
9794                                                         shortest[0].v1 = v1;
9795                                                         shortest[0].v2 = v2;
9796                                                 }
9797                                                 else if (shortest[1].length2 > l || i == 1)
9798                                                 {
9799                                                         shortest[1].length2 = l;
9800                                                         shortest[1].v1 = v1;
9801                                                         shortest[1].v2 = v2;
9802                                                 }
9803                                         }
9804                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9805                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9806                                         // this calculates the right vector from the shortest edge
9807                                         // and the up vector from the edge midpoints
9808                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9809                                         VectorNormalize(right);
9810                                         VectorSubtract(end, start, up);
9811                                         VectorNormalize(up);
9812                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9813                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9814                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9815                                         VectorNegate(forward, forward);
9816                                         VectorReflect(forward, 0, up, forward);
9817                                         VectorNormalize(forward);
9818                                         CrossProduct(up, forward, newright);
9819                                         VectorNormalize(newright);
9820                                         // rotate the quad around the up axis vector, this is made
9821                                         // especially easy by the fact we know the quad is flat,
9822                                         // so we only have to subtract the center position and
9823                                         // measure distance along the right vector, and then
9824                                         // multiply that by the newright vector and add back the
9825                                         // center position
9826                                         // we also need to subtract the old position to undo the
9827                                         // displacement from the center, which we do with a
9828                                         // DotProduct, the subtraction/addition of center is also
9829                                         // optimized into DotProducts here
9830                                         l = DotProduct(right, center);
9831                                         for (i = 0;i < 4;i++)
9832                                         {
9833                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9834                                                 f = DotProduct(right, v1) - l;
9835                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9836                                         }
9837                                 }
9838                         }
9839                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9840                         {
9841 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9842 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9843 //                              rsurface.batchnormal3f_bufferoffset = 0;
9844                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9845                         }
9846                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9847                         {
9848 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9849 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9850 //                              rsurface.batchsvector3f_bufferoffset = 0;
9851 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9852 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9853 //                              rsurface.batchtvector3f_bufferoffset = 0;
9854                                 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);
9855                         }
9856                         break;
9857                 case Q3DEFORM_NORMAL:
9858                         // deform the normals to make reflections wavey
9859                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9860                         rsurface.batchnormal3f_vertexbuffer = NULL;
9861                         rsurface.batchnormal3f_bufferoffset = 0;
9862                         for (j = 0;j < batchnumvertices;j++)
9863                         {
9864                                 float vertex[3];
9865                                 float *normal = rsurface.batchnormal3f + 3*j;
9866                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9867                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9868                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9869                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9870                                 VectorNormalize(normal);
9871                         }
9872                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9873                         {
9874 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9875 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9876 //                              rsurface.batchsvector3f_bufferoffset = 0;
9877 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9878 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9879 //                              rsurface.batchtvector3f_bufferoffset = 0;
9880                                 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);
9881                         }
9882                         break;
9883                 case Q3DEFORM_WAVE:
9884                         // deform vertex array to make wavey water and flags and such
9885                         waveparms[0] = deform->waveparms[0];
9886                         waveparms[1] = deform->waveparms[1];
9887                         waveparms[2] = deform->waveparms[2];
9888                         waveparms[3] = deform->waveparms[3];
9889                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9890                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9891                         // this is how a divisor of vertex influence on deformation
9892                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9893                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9894 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9895 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9896 //                      rsurface.batchvertex3f_bufferoffset = 0;
9897 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9898 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9899 //                      rsurface.batchnormal3f_bufferoffset = 0;
9900                         for (j = 0;j < batchnumvertices;j++)
9901                         {
9902                                 // if the wavefunc depends on time, evaluate it per-vertex
9903                                 if (waveparms[3])
9904                                 {
9905                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9906                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9907                                 }
9908                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9909                         }
9910                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9911                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9912                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9913                         {
9914 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9915 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9916 //                              rsurface.batchsvector3f_bufferoffset = 0;
9917 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9918 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9919 //                              rsurface.batchtvector3f_bufferoffset = 0;
9920                                 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);
9921                         }
9922                         break;
9923                 case Q3DEFORM_BULGE:
9924                         // deform vertex array to make the surface have moving bulges
9925 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9926 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9927 //                      rsurface.batchvertex3f_bufferoffset = 0;
9928 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9929 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9930 //                      rsurface.batchnormal3f_bufferoffset = 0;
9931                         for (j = 0;j < batchnumvertices;j++)
9932                         {
9933                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9934                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9935                         }
9936                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9937                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9938                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9939                         {
9940 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9941 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9942 //                              rsurface.batchsvector3f_bufferoffset = 0;
9943 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9944 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9945 //                              rsurface.batchtvector3f_bufferoffset = 0;
9946                                 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);
9947                         }
9948                         break;
9949                 case Q3DEFORM_MOVE:
9950                         // deform vertex array
9951                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9952                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9953                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9954                         VectorScale(deform->parms, scale, waveparms);
9955 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9956 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9957 //                      rsurface.batchvertex3f_bufferoffset = 0;
9958                         for (j = 0;j < batchnumvertices;j++)
9959                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9960                         break;
9961                 }
9962         }
9963
9964         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9965         {
9966         // generate texcoords based on the chosen texcoord source
9967                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9968                 {
9969                 default:
9970                 case Q3TCGEN_TEXTURE:
9971                         break;
9972                 case Q3TCGEN_LIGHTMAP:
9973         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9974         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9975         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9976                         if (rsurface.batchtexcoordlightmap2f)
9977                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9978                         break;
9979                 case Q3TCGEN_VECTOR:
9980         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9981         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9982         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9983                         for (j = 0;j < batchnumvertices;j++)
9984                         {
9985                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9986                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9987                         }
9988                         break;
9989                 case Q3TCGEN_ENVIRONMENT:
9990                         // make environment reflections using a spheremap
9991                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9992                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9993                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9994                         for (j = 0;j < batchnumvertices;j++)
9995                         {
9996                                 // identical to Q3A's method, but executed in worldspace so
9997                                 // carried models can be shiny too
9998
9999                                 float viewer[3], d, reflected[3], worldreflected[3];
10000
10001                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10002                                 // VectorNormalize(viewer);
10003
10004                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10005
10006                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10007                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10008                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10009                                 // note: this is proportinal to viewer, so we can normalize later
10010
10011                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10012                                 VectorNormalize(worldreflected);
10013
10014                                 // note: this sphere map only uses world x and z!
10015                                 // so positive and negative y will LOOK THE SAME.
10016                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10017                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10018                         }
10019                         break;
10020                 }
10021                 // the only tcmod that needs software vertex processing is turbulent, so
10022                 // check for it here and apply the changes if needed
10023                 // and we only support that as the first one
10024                 // (handling a mixture of turbulent and other tcmods would be problematic
10025                 //  without punting it entirely to a software path)
10026                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10027                 {
10028                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10029                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10030         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10031         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10032         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10033                         for (j = 0;j < batchnumvertices;j++)
10034                         {
10035                                 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);
10036                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10037                         }
10038                 }
10039         }
10040
10041         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10042         {
10043                 // convert the modified arrays to vertex structs
10044 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10045 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10046 //              rsurface.batchvertexmesh_bufferoffset = 0;
10047                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10048                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10049                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10050                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10051                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10052                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10053                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10054                 {
10055                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10056                         {
10057                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10058                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10059                         }
10060                 }
10061                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10062                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10063                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10064                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10065                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10066                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10067                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10068                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10069                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10070                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10071                 {
10072                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10073                         {
10074                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10075                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10076                         }
10077                 }
10078         }
10079
10080         // upload buffer data for the dynamic batch
10081         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10082         {
10083                 if (rsurface.batchvertexmesh)
10084                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10085                 else
10086                 {
10087                         if (rsurface.batchvertex3f)
10088                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10089                         if (rsurface.batchsvector3f)
10090                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10091                         if (rsurface.batchtvector3f)
10092                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10093                         if (rsurface.batchnormal3f)
10094                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10095                         if (rsurface.batchlightmapcolor4f)
10096                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10097                         if (rsurface.batchtexcoordtexture2f)
10098                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10099                         if (rsurface.batchtexcoordlightmap2f)
10100                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10101                         if (rsurface.batchskeletalindex4ub)
10102                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10103                         if (rsurface.batchskeletalweight4ub)
10104                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10105                 }
10106                 if (rsurface.batchelement3s)
10107                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10108                 else if (rsurface.batchelement3i)
10109                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10110         }
10111 }
10112
10113 void RSurf_DrawBatch(void)
10114 {
10115         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10116         // through the pipeline, killing it earlier in the pipeline would have
10117         // per-surface overhead rather than per-batch overhead, so it's best to
10118         // reject it here, before it hits glDraw.
10119         if (rsurface.batchnumtriangles == 0)
10120                 return;
10121 #if 0
10122         // batch debugging code
10123         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10124         {
10125                 int i;
10126                 int j;
10127                 int c;
10128                 const int *e;
10129                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10130                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10131                 {
10132                         c = e[i];
10133                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10134                         {
10135                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10136                                 {
10137                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10138                                                 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);
10139                                         break;
10140                                 }
10141                         }
10142                 }
10143         }
10144 #endif
10145         if (rsurface.batchmultidraw)
10146         {
10147                 // issue multiple draws rather than copying index data
10148                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10149                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10150                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10151                 for (i = 0;i < numsurfaces;)
10152                 {
10153                         // combine consecutive surfaces as one draw
10154                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10155                                 if (surfacelist[j] != surfacelist[k] + 1)
10156                                         break;
10157                         firstvertex = surfacelist[i]->num_firstvertex;
10158                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10159                         firsttriangle = surfacelist[i]->num_firsttriangle;
10160                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10161                         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);
10162                         i = j;
10163                 }
10164         }
10165         else
10166         {
10167                 // there is only one consecutive run of index data (may have been combined)
10168                 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);
10169         }
10170 }
10171
10172 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10173 {
10174         // pick the closest matching water plane
10175         int planeindex, vertexindex, bestplaneindex = -1;
10176         float d, bestd;
10177         vec3_t vert;
10178         const float *v;
10179         r_waterstate_waterplane_t *p;
10180         qboolean prepared = false;
10181         bestd = 0;
10182         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10183         {
10184                 if(p->camera_entity != rsurface.texture->camera_entity)
10185                         continue;
10186                 d = 0;
10187                 if(!prepared)
10188                 {
10189                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10190                         prepared = true;
10191                         if(rsurface.batchnumvertices == 0)
10192                                 break;
10193                 }
10194                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10195                 {
10196                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10197                         d += fabs(PlaneDiff(vert, &p->plane));
10198                 }
10199                 if (bestd > d || bestplaneindex < 0)
10200                 {
10201                         bestd = d;
10202                         bestplaneindex = planeindex;
10203                 }
10204         }
10205         return bestplaneindex;
10206         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10207         // this situation though, as it might be better to render single larger
10208         // batches with useless stuff (backface culled for example) than to
10209         // render multiple smaller batches
10210 }
10211
10212 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10213 {
10214         int i;
10215         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10216         rsurface.passcolor4f_vertexbuffer = 0;
10217         rsurface.passcolor4f_bufferoffset = 0;
10218         for (i = 0;i < rsurface.batchnumvertices;i++)
10219                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10220 }
10221
10222 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10223 {
10224         int i;
10225         float f;
10226         const float *v;
10227         const float *c;
10228         float *c2;
10229         if (rsurface.passcolor4f)
10230         {
10231                 // generate color arrays
10232                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10237                 {
10238                         f = RSurf_FogVertex(v);
10239                         c2[0] = c[0] * f;
10240                         c2[1] = c[1] * f;
10241                         c2[2] = c[2] * f;
10242                         c2[3] = c[3];
10243                 }
10244         }
10245         else
10246         {
10247                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10248                 rsurface.passcolor4f_vertexbuffer = 0;
10249                 rsurface.passcolor4f_bufferoffset = 0;
10250                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10251                 {
10252                         f = RSurf_FogVertex(v);
10253                         c2[0] = f;
10254                         c2[1] = f;
10255                         c2[2] = f;
10256                         c2[3] = 1;
10257                 }
10258         }
10259 }
10260
10261 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10262 {
10263         int i;
10264         float f;
10265         const float *v;
10266         const float *c;
10267         float *c2;
10268         if (!rsurface.passcolor4f)
10269                 return;
10270         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10271         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10272         rsurface.passcolor4f_vertexbuffer = 0;
10273         rsurface.passcolor4f_bufferoffset = 0;
10274         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)
10275         {
10276                 f = RSurf_FogVertex(v);
10277                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10278                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10279                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10280                 c2[3] = c[3];
10281         }
10282 }
10283
10284 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10285 {
10286         int i;
10287         const float *c;
10288         float *c2;
10289         if (!rsurface.passcolor4f)
10290                 return;
10291         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10292         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10293         rsurface.passcolor4f_vertexbuffer = 0;
10294         rsurface.passcolor4f_bufferoffset = 0;
10295         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10296         {
10297                 c2[0] = c[0] * r;
10298                 c2[1] = c[1] * g;
10299                 c2[2] = c[2] * b;
10300                 c2[3] = c[3] * a;
10301         }
10302 }
10303
10304 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10305 {
10306         int i;
10307         const float *c;
10308         float *c2;
10309         if (!rsurface.passcolor4f)
10310                 return;
10311         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10312         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10313         rsurface.passcolor4f_vertexbuffer = 0;
10314         rsurface.passcolor4f_bufferoffset = 0;
10315         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10316         {
10317                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10318                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10319                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10320                 c2[3] = c[3];
10321         }
10322 }
10323
10324 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10325 {
10326         // TODO: optimize
10327         rsurface.passcolor4f = NULL;
10328         rsurface.passcolor4f_vertexbuffer = 0;
10329         rsurface.passcolor4f_bufferoffset = 0;
10330         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10331         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10332         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10333         GL_Color(r, g, b, a);
10334         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10335         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10336         R_Mesh_TexMatrix(0, NULL);
10337         RSurf_DrawBatch();
10338 }
10339
10340 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10341 {
10342         // TODO: optimize applyfog && applycolor case
10343         // just apply fog if necessary, and tint the fog color array if necessary
10344         rsurface.passcolor4f = NULL;
10345         rsurface.passcolor4f_vertexbuffer = 0;
10346         rsurface.passcolor4f_bufferoffset = 0;
10347         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10348         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10349         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10350         GL_Color(r, g, b, a);
10351         RSurf_DrawBatch();
10352 }
10353
10354 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10355 {
10356         // TODO: optimize
10357         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10358         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10359         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10360         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10361         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10362         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10363         GL_Color(r, g, b, a);
10364         RSurf_DrawBatch();
10365 }
10366
10367 static void RSurf_DrawBatch_GL11_ClampColor(void)
10368 {
10369         int i;
10370         const float *c1;
10371         float *c2;
10372         if (!rsurface.passcolor4f)
10373                 return;
10374         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10375         {
10376                 c2[0] = bound(0.0f, c1[0], 1.0f);
10377                 c2[1] = bound(0.0f, c1[1], 1.0f);
10378                 c2[2] = bound(0.0f, c1[2], 1.0f);
10379                 c2[3] = bound(0.0f, c1[3], 1.0f);
10380         }
10381 }
10382
10383 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10384 {
10385         int i;
10386         float f;
10387         const float *v;
10388         const float *n;
10389         float *c;
10390         //vec3_t eyedir;
10391
10392         // fake shading
10393         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394         rsurface.passcolor4f_vertexbuffer = 0;
10395         rsurface.passcolor4f_bufferoffset = 0;
10396         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)
10397         {
10398                 f = -DotProduct(r_refdef.view.forward, n);
10399                 f = max(0, f);
10400                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10401                 f *= fakelightintensity;
10402                 Vector4Set(c, f, f, f, 1);
10403         }
10404 }
10405
10406 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10407 {
10408         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10409         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10410         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10411         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10412         GL_Color(r, g, b, a);
10413         RSurf_DrawBatch();
10414 }
10415
10416 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10417 {
10418         int i;
10419         float f;
10420         float alpha;
10421         const float *v;
10422         const float *n;
10423         float *c;
10424         vec3_t ambientcolor;
10425         vec3_t diffusecolor;
10426         vec3_t lightdir;
10427         // TODO: optimize
10428         // model lighting
10429         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10430         f = 0.5f * lightmapintensity;
10431         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10432         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10433         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10434         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10435         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10436         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10437         alpha = *a;
10438         if (VectorLength2(diffusecolor) > 0)
10439         {
10440                 // q3-style directional shading
10441                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10442                 rsurface.passcolor4f_vertexbuffer = 0;
10443                 rsurface.passcolor4f_bufferoffset = 0;
10444                 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)
10445                 {
10446                         if ((f = DotProduct(n, lightdir)) > 0)
10447                                 VectorMA(ambientcolor, f, diffusecolor, c);
10448                         else
10449                                 VectorCopy(ambientcolor, c);
10450                         c[3] = alpha;
10451                 }
10452                 *r = 1;
10453                 *g = 1;
10454                 *b = 1;
10455                 *a = 1;
10456                 *applycolor = false;
10457         }
10458         else
10459         {
10460                 *r = ambientcolor[0];
10461                 *g = ambientcolor[1];
10462                 *b = ambientcolor[2];
10463                 rsurface.passcolor4f = NULL;
10464                 rsurface.passcolor4f_vertexbuffer = 0;
10465                 rsurface.passcolor4f_bufferoffset = 0;
10466         }
10467 }
10468
10469 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10470 {
10471         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10472         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10473         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10474         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10475         GL_Color(r, g, b, a);
10476         RSurf_DrawBatch();
10477 }
10478
10479 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10480 {
10481         int i;
10482         float f;
10483         const float *v;
10484         float *c;
10485
10486         // fake shading
10487         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10488         rsurface.passcolor4f_vertexbuffer = 0;
10489         rsurface.passcolor4f_bufferoffset = 0;
10490
10491         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10492         {
10493                 f = 1 - RSurf_FogVertex(v);
10494                 c[0] = r;
10495                 c[1] = g;
10496                 c[2] = b;
10497                 c[3] = f * a;
10498         }
10499 }
10500
10501 void RSurf_SetupDepthAndCulling(void)
10502 {
10503         // submodels are biased to avoid z-fighting with world surfaces that they
10504         // may be exactly overlapping (avoids z-fighting artifacts on certain
10505         // doors and things in Quake maps)
10506         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10507         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10508         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10509         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10510 }
10511
10512 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10513 {
10514         int i, j;
10515         // transparent sky would be ridiculous
10516         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10517                 return;
10518         R_SetupShader_Generic_NoTexture(false, false);
10519         skyrenderlater = true;
10520         RSurf_SetupDepthAndCulling();
10521         GL_DepthMask(true);
10522
10523         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10524         if (r_sky_scissor.integer)
10525         {
10526                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10527                 for (i = 0; i < texturenumsurfaces; i++)
10528                 {
10529                         const msurface_t *surf = texturesurfacelist[i];
10530                         const float *v;
10531                         float p[3];
10532                         float mins[3], maxs[3];
10533                         int scissor[4];
10534                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10535                         {
10536                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10537                                 if (j > 0)
10538                                 {
10539                                         if (mins[0] > p[0]) mins[0] = p[0];
10540                                         if (mins[1] > p[1]) mins[1] = p[1];
10541                                         if (mins[2] > p[2]) mins[2] = p[2];
10542                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10543                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10544                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10545                                 }
10546                                 else
10547                                 {
10548                                         VectorCopy(p, mins);
10549                                         VectorCopy(p, maxs);
10550                                 }
10551                         }
10552                         if (!R_ScissorForBBox(mins, maxs, scissor))
10553                         {
10554                                 if (skyscissor[2])
10555                                 {
10556                                         if (skyscissor[0] > scissor[0])
10557                                         {
10558                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10559                                                 skyscissor[0] = scissor[0];
10560                                         }
10561                                         if (skyscissor[1] > scissor[1])
10562                                         {
10563                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10564                                                 skyscissor[1] = scissor[1];
10565                                         }
10566                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10567                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10568                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10569                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10570                                 }
10571                                 else
10572                                         Vector4Copy(scissor, skyscissor);
10573                         }
10574                 }
10575         }
10576
10577         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10578         // skymasking on them, and Quake3 never did sky masking (unlike
10579         // software Quake and software Quake2), so disable the sky masking
10580         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10581         // and skymasking also looks very bad when noclipping outside the
10582         // level, so don't use it then either.
10583         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)
10584         {
10585                 R_Mesh_ResetTextureState();
10586                 if (skyrendermasked)
10587                 {
10588                         R_SetupShader_DepthOrShadow(false, false, false);
10589                         // depth-only (masking)
10590                         GL_ColorMask(0, 0, 0, 0);
10591                         // just to make sure that braindead drivers don't draw
10592                         // anything despite that colormask...
10593                         GL_BlendFunc(GL_ZERO, GL_ONE);
10594                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10595                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10596                 }
10597                 else
10598                 {
10599                         R_SetupShader_Generic_NoTexture(false, false);
10600                         // fog sky
10601                         GL_BlendFunc(GL_ONE, GL_ZERO);
10602                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10603                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10604                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10605                 }
10606                 RSurf_DrawBatch();
10607                 if (skyrendermasked)
10608                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10609         }
10610         R_Mesh_ResetTextureState();
10611         GL_Color(1, 1, 1, 1);
10612 }
10613
10614 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10615 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10616 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10617 {
10618         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10619                 return;
10620         if (prepass)
10621         {
10622                 // render screenspace normalmap to texture
10623                 GL_DepthMask(true);
10624                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10625                 RSurf_DrawBatch();
10626                 return;
10627         }
10628
10629         // bind lightmap texture
10630
10631         // water/refraction/reflection/camera surfaces have to be handled specially
10632         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10633         {
10634                 int start, end, startplaneindex;
10635                 for (start = 0;start < texturenumsurfaces;start = end)
10636                 {
10637                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10638                         if(startplaneindex < 0)
10639                         {
10640                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10641                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10642                                 end = start + 1;
10643                                 continue;
10644                         }
10645                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10646                                 ;
10647                         // now that we have a batch using the same planeindex, render it
10648                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10649                         {
10650                                 // render water or distortion background
10651                                 GL_DepthMask(true);
10652                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10653                                 RSurf_DrawBatch();
10654                                 // blend surface on top
10655                                 GL_DepthMask(false);
10656                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10657                                 RSurf_DrawBatch();
10658                         }
10659                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10660                         {
10661                                 // render surface with reflection texture as input
10662                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10663                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10664                                 RSurf_DrawBatch();
10665                         }
10666                 }
10667                 return;
10668         }
10669
10670         // render surface batch normally
10671         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10672         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10673         RSurf_DrawBatch();
10674 }
10675
10676 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10677 {
10678         // OpenGL 1.3 path - anything not completely ancient
10679         qboolean applycolor;
10680         qboolean applyfog;
10681         int layerindex;
10682         const texturelayer_t *layer;
10683         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);
10684         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10685
10686         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10687         {
10688                 vec4_t layercolor;
10689                 int layertexrgbscale;
10690                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10691                 {
10692                         if (layerindex == 0)
10693                                 GL_AlphaTest(true);
10694                         else
10695                         {
10696                                 GL_AlphaTest(false);
10697                                 GL_DepthFunc(GL_EQUAL);
10698                         }
10699                 }
10700                 GL_DepthMask(layer->depthmask && writedepth);
10701                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10702                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10703                 {
10704                         layertexrgbscale = 4;
10705                         VectorScale(layer->color, 0.25f, layercolor);
10706                 }
10707                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10708                 {
10709                         layertexrgbscale = 2;
10710                         VectorScale(layer->color, 0.5f, layercolor);
10711                 }
10712                 else
10713                 {
10714                         layertexrgbscale = 1;
10715                         VectorScale(layer->color, 1.0f, layercolor);
10716                 }
10717                 layercolor[3] = layer->color[3];
10718                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10719                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10720                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10721                 switch (layer->type)
10722                 {
10723                 case TEXTURELAYERTYPE_LITTEXTURE:
10724                         // single-pass lightmapped texture with 2x rgbscale
10725                         R_Mesh_TexBind(0, r_texture_white);
10726                         R_Mesh_TexMatrix(0, NULL);
10727                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10728                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10729                         R_Mesh_TexBind(1, layer->texture);
10730                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10731                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10732                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10733                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10734                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10735                         else if (FAKELIGHT_ENABLED)
10736                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10737                         else if (rsurface.uselightmaptexture)
10738                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10739                         else
10740                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10741                         break;
10742                 case TEXTURELAYERTYPE_TEXTURE:
10743                         // singletexture unlit texture with transparency support
10744                         R_Mesh_TexBind(0, layer->texture);
10745                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10746                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10747                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10748                         R_Mesh_TexBind(1, 0);
10749                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10750                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10751                         break;
10752                 case TEXTURELAYERTYPE_FOG:
10753                         // singletexture fogging
10754                         if (layer->texture)
10755                         {
10756                                 R_Mesh_TexBind(0, layer->texture);
10757                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10758                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10759                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10760                         }
10761                         else
10762                         {
10763                                 R_Mesh_TexBind(0, 0);
10764                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10765                         }
10766                         R_Mesh_TexBind(1, 0);
10767                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10768                         // generate a color array for the fog pass
10769                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10770                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10771                         RSurf_DrawBatch();
10772                         break;
10773                 default:
10774                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10775                 }
10776         }
10777         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10778         {
10779                 GL_DepthFunc(GL_LEQUAL);
10780                 GL_AlphaTest(false);
10781         }
10782 }
10783
10784 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10785 {
10786         // OpenGL 1.1 - crusty old voodoo path
10787         qboolean applyfog;
10788         int layerindex;
10789         const texturelayer_t *layer;
10790         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);
10791         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10792
10793         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10794         {
10795                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10796                 {
10797                         if (layerindex == 0)
10798                                 GL_AlphaTest(true);
10799                         else
10800                         {
10801                                 GL_AlphaTest(false);
10802                                 GL_DepthFunc(GL_EQUAL);
10803                         }
10804                 }
10805                 GL_DepthMask(layer->depthmask && writedepth);
10806                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10807                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10808                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10809                 switch (layer->type)
10810                 {
10811                 case TEXTURELAYERTYPE_LITTEXTURE:
10812                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10813                         {
10814                                 // two-pass lit texture with 2x rgbscale
10815                                 // first the lightmap pass
10816                                 R_Mesh_TexBind(0, r_texture_white);
10817                                 R_Mesh_TexMatrix(0, NULL);
10818                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10819                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10820                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10821                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10822                                 else if (FAKELIGHT_ENABLED)
10823                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10824                                 else if (rsurface.uselightmaptexture)
10825                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10826                                 else
10827                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10828                                 // then apply the texture to it
10829                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10830                                 R_Mesh_TexBind(0, layer->texture);
10831                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10832                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10834                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 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);
10835                         }
10836                         else
10837                         {
10838                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10839                                 R_Mesh_TexBind(0, layer->texture);
10840                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10841                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10842                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10843                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10844                                         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);
10845                                 else if (FAKELIGHT_ENABLED)
10846                                         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);
10847                                 else
10848                                         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);
10849                         }
10850                         break;
10851                 case TEXTURELAYERTYPE_TEXTURE:
10852                         // singletexture unlit texture with transparency support
10853                         R_Mesh_TexBind(0, layer->texture);
10854                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10855                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10856                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10857                         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);
10858                         break;
10859                 case TEXTURELAYERTYPE_FOG:
10860                         // singletexture fogging
10861                         if (layer->texture)
10862                         {
10863                                 R_Mesh_TexBind(0, layer->texture);
10864                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10865                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10866                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10867                         }
10868                         else
10869                         {
10870                                 R_Mesh_TexBind(0, 0);
10871                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10872                         }
10873                         // generate a color array for the fog pass
10874                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10875                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10876                         RSurf_DrawBatch();
10877                         break;
10878                 default:
10879                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10880                 }
10881         }
10882         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10883         {
10884                 GL_DepthFunc(GL_LEQUAL);
10885                 GL_AlphaTest(false);
10886         }
10887 }
10888
10889 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10890 {
10891         int vi;
10892         int j;
10893         r_vertexgeneric_t *batchvertex;
10894         float c[4];
10895         texture_t *t = rsurface.texture;
10896
10897 //      R_Mesh_ResetTextureState();
10898         R_SetupShader_Generic_NoTexture(false, false);
10899
10900         if(t && t->currentskinframe)
10901         {
10902                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10903                 c[3] *= t->currentalpha;
10904         }
10905         else
10906         {
10907                 c[0] = 1;
10908                 c[1] = 0;
10909                 c[2] = 1;
10910                 c[3] = 1;
10911         }
10912
10913         if (t->pantstexture || t->shirttexture)
10914         {
10915                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10916                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10917                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10918         }
10919
10920         // brighten it up (as texture value 127 means "unlit")
10921         c[0] *= 2 * r_refdef.view.colorscale;
10922         c[1] *= 2 * r_refdef.view.colorscale;
10923         c[2] *= 2 * r_refdef.view.colorscale;
10924
10925         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10926                 c[3] *= r_wateralpha.value;
10927
10928         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10929         {
10930                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10931                 GL_DepthMask(false);
10932         }
10933         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10934         {
10935                 GL_BlendFunc(GL_ONE, GL_ONE);
10936                 GL_DepthMask(false);
10937         }
10938         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10939         {
10940                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10941                 GL_DepthMask(false);
10942         }
10943         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10944         {
10945                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10946                 GL_DepthMask(false);
10947         }
10948         else
10949         {
10950                 GL_BlendFunc(GL_ONE, GL_ZERO);
10951                 GL_DepthMask(writedepth);
10952         }
10953
10954         if (r_showsurfaces.integer == 3)
10955         {
10956                 rsurface.passcolor4f = NULL;
10957
10958                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10959                 {
10960                         qboolean applycolor = true;
10961                         float one = 1.0;
10962
10963                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10964
10965                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10966                 }
10967                 else if (FAKELIGHT_ENABLED)
10968                 {
10969                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10970
10971                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10972                 }
10973                 else
10974                 {
10975                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10976
10977                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10978                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10979                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10980                         RSurf_DrawBatch_GL11_ApplyAmbient();
10981                 }
10982
10983                 if(!rsurface.passcolor4f)
10984                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10985
10986                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10987                 if(r_refdef.fogenabled)
10988                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10989                 RSurf_DrawBatch_GL11_ClampColor();
10990
10991                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10992                 R_SetupShader_Generic_NoTexture(false, false);
10993                 RSurf_DrawBatch();
10994         }
10995         else if (!r_refdef.view.showdebug)
10996         {
10997                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10998                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10999                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11000                 {
11001                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11002                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11003                 }
11004                 R_Mesh_PrepareVertices_Generic_Unlock();
11005                 RSurf_DrawBatch();
11006         }
11007         else if (r_showsurfaces.integer == 4)
11008         {
11009                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11010                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11011                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11012                 {
11013                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11014                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11015                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11016                 }
11017                 R_Mesh_PrepareVertices_Generic_Unlock();
11018                 RSurf_DrawBatch();
11019         }
11020         else if (r_showsurfaces.integer == 2)
11021         {
11022                 const int *e;
11023                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11025                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11026                 {
11027                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11028                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11029                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11030                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11031                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11032                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11033                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11034                 }
11035                 R_Mesh_PrepareVertices_Generic_Unlock();
11036                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11037         }
11038         else
11039         {
11040                 int texturesurfaceindex;
11041                 int k;
11042                 const msurface_t *surface;
11043                 float surfacecolor4f[4];
11044                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11046                 vi = 0;
11047                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11048                 {
11049                         surface = texturesurfacelist[texturesurfaceindex];
11050                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11051                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11052                         for (j = 0;j < surface->num_vertices;j++)
11053                         {
11054                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11055                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11056                                 vi++;
11057                         }
11058                 }
11059                 R_Mesh_PrepareVertices_Generic_Unlock();
11060                 RSurf_DrawBatch();
11061         }
11062 }
11063
11064 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11065 {
11066         CHECKGLERROR
11067         RSurf_SetupDepthAndCulling();
11068         if (r_showsurfaces.integer)
11069         {
11070                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11071                 return;
11072         }
11073         switch (vid.renderpath)
11074         {
11075         case RENDERPATH_GL20:
11076         case RENDERPATH_D3D9:
11077         case RENDERPATH_D3D10:
11078         case RENDERPATH_D3D11:
11079         case RENDERPATH_SOFT:
11080         case RENDERPATH_GLES2:
11081                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11082                 break;
11083         case RENDERPATH_GL13:
11084         case RENDERPATH_GLES1:
11085                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11086                 break;
11087         case RENDERPATH_GL11:
11088                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11089                 break;
11090         }
11091         CHECKGLERROR
11092 }
11093
11094 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11095 {
11096         int i, j;
11097         int texturenumsurfaces, endsurface;
11098         texture_t *texture;
11099         const msurface_t *surface;
11100         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11101
11102         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11103                 RSurf_ActiveModelEntity(ent, false, false, false);
11104         else
11105         {
11106                 switch (vid.renderpath)
11107                 {
11108                 case RENDERPATH_GL20:
11109                 case RENDERPATH_D3D9:
11110                 case RENDERPATH_D3D10:
11111                 case RENDERPATH_D3D11:
11112                 case RENDERPATH_SOFT:
11113                 case RENDERPATH_GLES2:
11114                         RSurf_ActiveModelEntity(ent, true, true, false);
11115                         break;
11116                 case RENDERPATH_GL11:
11117                 case RENDERPATH_GL13:
11118                 case RENDERPATH_GLES1:
11119                         RSurf_ActiveModelEntity(ent, true, false, false);
11120                         break;
11121                 }
11122         }
11123
11124         if (r_transparentdepthmasking.integer)
11125         {
11126                 qboolean setup = false;
11127                 for (i = 0;i < numsurfaces;i = j)
11128                 {
11129                         j = i + 1;
11130                         surface = rsurface.modelsurfaces + surfacelist[i];
11131                         texture = surface->texture;
11132                         rsurface.texture = R_GetCurrentTexture(texture);
11133                         rsurface.lightmaptexture = NULL;
11134                         rsurface.deluxemaptexture = NULL;
11135                         rsurface.uselightmaptexture = false;
11136                         // scan ahead until we find a different texture
11137                         endsurface = min(i + 1024, numsurfaces);
11138                         texturenumsurfaces = 0;
11139                         texturesurfacelist[texturenumsurfaces++] = surface;
11140                         for (;j < endsurface;j++)
11141                         {
11142                                 surface = rsurface.modelsurfaces + surfacelist[j];
11143                                 if (texture != surface->texture)
11144                                         break;
11145                                 texturesurfacelist[texturenumsurfaces++] = surface;
11146                         }
11147                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11148                                 continue;
11149                         // render the range of surfaces as depth
11150                         if (!setup)
11151                         {
11152                                 setup = true;
11153                                 GL_ColorMask(0,0,0,0);
11154                                 GL_Color(1,1,1,1);
11155                                 GL_DepthTest(true);
11156                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11157                                 GL_DepthMask(true);
11158 //                              R_Mesh_ResetTextureState();
11159                         }
11160                         RSurf_SetupDepthAndCulling();
11161                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11162                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11163                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11164                         RSurf_DrawBatch();
11165                 }
11166                 if (setup)
11167                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11168         }
11169
11170         for (i = 0;i < numsurfaces;i = j)
11171         {
11172                 j = i + 1;
11173                 surface = rsurface.modelsurfaces + surfacelist[i];
11174                 texture = surface->texture;
11175                 rsurface.texture = R_GetCurrentTexture(texture);
11176                 // scan ahead until we find a different texture
11177                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11178                 texturenumsurfaces = 0;
11179                 texturesurfacelist[texturenumsurfaces++] = surface;
11180                 if(FAKELIGHT_ENABLED)
11181                 {
11182                         rsurface.lightmaptexture = NULL;
11183                         rsurface.deluxemaptexture = NULL;
11184                         rsurface.uselightmaptexture = false;
11185                         for (;j < endsurface;j++)
11186                         {
11187                                 surface = rsurface.modelsurfaces + surfacelist[j];
11188                                 if (texture != surface->texture)
11189                                         break;
11190                                 texturesurfacelist[texturenumsurfaces++] = surface;
11191                         }
11192                 }
11193                 else
11194                 {
11195                         rsurface.lightmaptexture = surface->lightmaptexture;
11196                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11197                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11198                         for (;j < endsurface;j++)
11199                         {
11200                                 surface = rsurface.modelsurfaces + surfacelist[j];
11201                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11202                                         break;
11203                                 texturesurfacelist[texturenumsurfaces++] = surface;
11204                         }
11205                 }
11206                 // render the range of surfaces
11207                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11208         }
11209         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11210 }
11211
11212 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11213 {
11214         // transparent surfaces get pushed off into the transparent queue
11215         int surfacelistindex;
11216         const msurface_t *surface;
11217         vec3_t tempcenter, center;
11218         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11219         {
11220                 surface = texturesurfacelist[surfacelistindex];
11221                 if (r_transparent_sortsurfacesbynearest.integer)
11222                 {
11223                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11224                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11225                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11226                 }
11227                 else
11228                 {
11229                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11230                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11231                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11232                 }
11233                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11234                 if (rsurface.entity->transparent_offset) // transparent offset
11235                 {
11236                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11237                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11238                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11239                 }
11240                 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);
11241         }
11242 }
11243
11244 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11245 {
11246         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11247                 return;
11248         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11249                 return;
11250         RSurf_SetupDepthAndCulling();
11251         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11252         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11253         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11254         RSurf_DrawBatch();
11255 }
11256
11257 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11258 {
11259         CHECKGLERROR
11260         if (depthonly)
11261                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11262         else if (prepass)
11263         {
11264                 if (!rsurface.texture->currentnumlayers)
11265                         return;
11266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11267                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11268                 else
11269                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11270         }
11271         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11272                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11273         else if (!rsurface.texture->currentnumlayers)
11274                 return;
11275         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11276         {
11277                 // in the deferred case, transparent surfaces were queued during prepass
11278                 if (!r_shadow_usingdeferredprepass)
11279                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11280         }
11281         else
11282         {
11283                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11284                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11285         }
11286         CHECKGLERROR
11287 }
11288
11289 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11290 {
11291         int i, j;
11292         texture_t *texture;
11293         R_FrameData_SetMark();
11294         // break the surface list down into batches by texture and use of lightmapping
11295         for (i = 0;i < numsurfaces;i = j)
11296         {
11297                 j = i + 1;
11298                 // texture is the base texture pointer, rsurface.texture is the
11299                 // current frame/skin the texture is directing us to use (for example
11300                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11301                 // use skin 1 instead)
11302                 texture = surfacelist[i]->texture;
11303                 rsurface.texture = R_GetCurrentTexture(texture);
11304                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11305                 {
11306                         // if this texture is not the kind we want, skip ahead to the next one
11307                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11308                                 ;
11309                         continue;
11310                 }
11311                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11312                 {
11313                         rsurface.lightmaptexture = NULL;
11314                         rsurface.deluxemaptexture = NULL;
11315                         rsurface.uselightmaptexture = false;
11316                         // simply scan ahead until we find a different texture or lightmap state
11317                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11318                                 ;
11319                 }
11320                 else
11321                 {
11322                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11323                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11324                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11325                         // simply scan ahead until we find a different texture or lightmap state
11326                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11327                                 ;
11328                 }
11329                 // render the range of surfaces
11330                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11331         }
11332         R_FrameData_ReturnToMark();
11333 }
11334
11335 float locboxvertex3f[6*4*3] =
11336 {
11337         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11338         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11339         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11340         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11341         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11342         1,0,0, 0,0,0, 0,1,0, 1,1,0
11343 };
11344
11345 unsigned short locboxelements[6*2*3] =
11346 {
11347          0, 1, 2, 0, 2, 3,
11348          4, 5, 6, 4, 6, 7,
11349          8, 9,10, 8,10,11,
11350         12,13,14, 12,14,15,
11351         16,17,18, 16,18,19,
11352         20,21,22, 20,22,23
11353 };
11354
11355 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11356 {
11357         int i, j;
11358         cl_locnode_t *loc = (cl_locnode_t *)ent;
11359         vec3_t mins, size;
11360         float vertex3f[6*4*3];
11361         CHECKGLERROR
11362         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11363         GL_DepthMask(false);
11364         GL_DepthRange(0, 1);
11365         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11366         GL_DepthTest(true);
11367         GL_CullFace(GL_NONE);
11368         R_EntityMatrix(&identitymatrix);
11369
11370 //      R_Mesh_ResetTextureState();
11371
11372         i = surfacelist[0];
11373         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11374                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11375                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11376                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11377
11378         if (VectorCompare(loc->mins, loc->maxs))
11379         {
11380                 VectorSet(size, 2, 2, 2);
11381                 VectorMA(loc->mins, -0.5f, size, mins);
11382         }
11383         else
11384         {
11385                 VectorCopy(loc->mins, mins);
11386                 VectorSubtract(loc->maxs, loc->mins, size);
11387         }
11388
11389         for (i = 0;i < 6*4*3;)
11390                 for (j = 0;j < 3;j++, i++)
11391                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11392
11393         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11394         R_SetupShader_Generic_NoTexture(false, false);
11395         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11396 }
11397
11398 void R_DrawLocs(void)
11399 {
11400         int index;
11401         cl_locnode_t *loc, *nearestloc;
11402         vec3_t center;
11403         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11404         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11405         {
11406                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11407                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11408         }
11409 }
11410
11411 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11412 {
11413         if (decalsystem->decals)
11414                 Mem_Free(decalsystem->decals);
11415         memset(decalsystem, 0, sizeof(*decalsystem));
11416 }
11417
11418 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)
11419 {
11420         tridecal_t *decal;
11421         tridecal_t *decals;
11422         int i;
11423
11424         // expand or initialize the system
11425         if (decalsystem->maxdecals <= decalsystem->numdecals)
11426         {
11427                 decalsystem_t old = *decalsystem;
11428                 qboolean useshortelements;
11429                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11430                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11431                 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)));
11432                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11433                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11434                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11435                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11436                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11437                 if (decalsystem->numdecals)
11438                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11439                 if (old.decals)
11440                         Mem_Free(old.decals);
11441                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11442                         decalsystem->element3i[i] = i;
11443                 if (useshortelements)
11444                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11445                                 decalsystem->element3s[i] = i;
11446         }
11447
11448         // grab a decal and search for another free slot for the next one
11449         decals = decalsystem->decals;
11450         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11451         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11452                 ;
11453         decalsystem->freedecal = i;
11454         if (decalsystem->numdecals <= i)
11455                 decalsystem->numdecals = i + 1;
11456
11457         // initialize the decal
11458         decal->lived = 0;
11459         decal->triangleindex = triangleindex;
11460         decal->surfaceindex = surfaceindex;
11461         decal->decalsequence = decalsequence;
11462         decal->color4f[0][0] = c0[0];
11463         decal->color4f[0][1] = c0[1];
11464         decal->color4f[0][2] = c0[2];
11465         decal->color4f[0][3] = 1;
11466         decal->color4f[1][0] = c1[0];
11467         decal->color4f[1][1] = c1[1];
11468         decal->color4f[1][2] = c1[2];
11469         decal->color4f[1][3] = 1;
11470         decal->color4f[2][0] = c2[0];
11471         decal->color4f[2][1] = c2[1];
11472         decal->color4f[2][2] = c2[2];
11473         decal->color4f[2][3] = 1;
11474         decal->vertex3f[0][0] = v0[0];
11475         decal->vertex3f[0][1] = v0[1];
11476         decal->vertex3f[0][2] = v0[2];
11477         decal->vertex3f[1][0] = v1[0];
11478         decal->vertex3f[1][1] = v1[1];
11479         decal->vertex3f[1][2] = v1[2];
11480         decal->vertex3f[2][0] = v2[0];
11481         decal->vertex3f[2][1] = v2[1];
11482         decal->vertex3f[2][2] = v2[2];
11483         decal->texcoord2f[0][0] = t0[0];
11484         decal->texcoord2f[0][1] = t0[1];
11485         decal->texcoord2f[1][0] = t1[0];
11486         decal->texcoord2f[1][1] = t1[1];
11487         decal->texcoord2f[2][0] = t2[0];
11488         decal->texcoord2f[2][1] = t2[1];
11489         TriangleNormal(v0, v1, v2, decal->plane);
11490         VectorNormalize(decal->plane);
11491         decal->plane[3] = DotProduct(v0, decal->plane);
11492 }
11493
11494 extern cvar_t cl_decals_bias;
11495 extern cvar_t cl_decals_models;
11496 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11497 // baseparms, parms, temps
11498 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)
11499 {
11500         int cornerindex;
11501         int index;
11502         float v[9][3];
11503         const float *vertex3f;
11504         const float *normal3f;
11505         int numpoints;
11506         float points[2][9][3];
11507         float temp[3];
11508         float tc[9][2];
11509         float f;
11510         float c[9][4];
11511         const int *e;
11512
11513         e = rsurface.modelelement3i + 3*triangleindex;
11514
11515         vertex3f = rsurface.modelvertex3f;
11516         normal3f = rsurface.modelnormal3f;
11517
11518         if (normal3f)
11519         {
11520                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11521                 {
11522                         index = 3*e[cornerindex];
11523                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11524                 }
11525         }
11526         else
11527         {
11528                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11529                 {
11530                         index = 3*e[cornerindex];
11531                         VectorCopy(vertex3f + index, v[cornerindex]);
11532                 }
11533         }
11534
11535         // cull backfaces
11536         //TriangleNormal(v[0], v[1], v[2], normal);
11537         //if (DotProduct(normal, localnormal) < 0.0f)
11538         //      continue;
11539         // clip by each of the box planes formed from the projection matrix
11540         // if anything survives, we emit the decal
11541         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]);
11542         if (numpoints < 3)
11543                 return;
11544         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]);
11545         if (numpoints < 3)
11546                 return;
11547         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]);
11548         if (numpoints < 3)
11549                 return;
11550         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]);
11551         if (numpoints < 3)
11552                 return;
11553         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]);
11554         if (numpoints < 3)
11555                 return;
11556         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]);
11557         if (numpoints < 3)
11558                 return;
11559         // some part of the triangle survived, so we have to accept it...
11560         if (dynamic)
11561         {
11562                 // dynamic always uses the original triangle
11563                 numpoints = 3;
11564                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11565                 {
11566                         index = 3*e[cornerindex];
11567                         VectorCopy(vertex3f + index, v[cornerindex]);
11568                 }
11569         }
11570         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11571         {
11572                 // convert vertex positions to texcoords
11573                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11574                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11575                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11576                 // calculate distance fade from the projection origin
11577                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11578                 f = bound(0.0f, f, 1.0f);
11579                 c[cornerindex][0] = r * f;
11580                 c[cornerindex][1] = g * f;
11581                 c[cornerindex][2] = b * f;
11582                 c[cornerindex][3] = 1.0f;
11583                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11584         }
11585         if (dynamic)
11586                 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);
11587         else
11588                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11589                         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);
11590 }
11591 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)
11592 {
11593         matrix4x4_t projection;
11594         decalsystem_t *decalsystem;
11595         qboolean dynamic;
11596         dp_model_t *model;
11597         const msurface_t *surface;
11598         const msurface_t *surfaces;
11599         const int *surfacelist;
11600         const texture_t *texture;
11601         int numtriangles;
11602         int numsurfacelist;
11603         int surfacelistindex;
11604         int surfaceindex;
11605         int triangleindex;
11606         float localorigin[3];
11607         float localnormal[3];
11608         float localmins[3];
11609         float localmaxs[3];
11610         float localsize;
11611         //float normal[3];
11612         float planes[6][4];
11613         float angles[3];
11614         bih_t *bih;
11615         int bih_triangles_count;
11616         int bih_triangles[256];
11617         int bih_surfaces[256];
11618
11619         decalsystem = &ent->decalsystem;
11620         model = ent->model;
11621         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11622         {
11623                 R_DecalSystem_Reset(&ent->decalsystem);
11624                 return;
11625         }
11626
11627         if (!model->brush.data_leafs && !cl_decals_models.integer)
11628         {
11629                 if (decalsystem->model)
11630                         R_DecalSystem_Reset(decalsystem);
11631                 return;
11632         }
11633
11634         if (decalsystem->model != model)
11635                 R_DecalSystem_Reset(decalsystem);
11636         decalsystem->model = model;
11637
11638         RSurf_ActiveModelEntity(ent, true, false, false);
11639
11640         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11641         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11642         VectorNormalize(localnormal);
11643         localsize = worldsize*rsurface.inversematrixscale;
11644         localmins[0] = localorigin[0] - localsize;
11645         localmins[1] = localorigin[1] - localsize;
11646         localmins[2] = localorigin[2] - localsize;
11647         localmaxs[0] = localorigin[0] + localsize;
11648         localmaxs[1] = localorigin[1] + localsize;
11649         localmaxs[2] = localorigin[2] + localsize;
11650
11651         //VectorCopy(localnormal, planes[4]);
11652         //VectorVectors(planes[4], planes[2], planes[0]);
11653         AnglesFromVectors(angles, localnormal, NULL, false);
11654         AngleVectors(angles, planes[0], planes[2], planes[4]);
11655         VectorNegate(planes[0], planes[1]);
11656         VectorNegate(planes[2], planes[3]);
11657         VectorNegate(planes[4], planes[5]);
11658         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11659         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11660         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11661         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11662         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11663         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11664
11665 #if 1
11666 // works
11667 {
11668         matrix4x4_t forwardprojection;
11669         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11670         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11671 }
11672 #else
11673 // broken
11674 {
11675         float projectionvector[4][3];
11676         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11677         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11678         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11679         projectionvector[0][0] = planes[0][0] * ilocalsize;
11680         projectionvector[0][1] = planes[1][0] * ilocalsize;
11681         projectionvector[0][2] = planes[2][0] * ilocalsize;
11682         projectionvector[1][0] = planes[0][1] * ilocalsize;
11683         projectionvector[1][1] = planes[1][1] * ilocalsize;
11684         projectionvector[1][2] = planes[2][1] * ilocalsize;
11685         projectionvector[2][0] = planes[0][2] * ilocalsize;
11686         projectionvector[2][1] = planes[1][2] * ilocalsize;
11687         projectionvector[2][2] = planes[2][2] * ilocalsize;
11688         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11689         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11690         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11691         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11692 }
11693 #endif
11694
11695         dynamic = model->surfmesh.isanimated;
11696         numsurfacelist = model->nummodelsurfaces;
11697         surfacelist = model->sortedmodelsurfaces;
11698         surfaces = model->data_surfaces;
11699
11700         bih = NULL;
11701         bih_triangles_count = -1;
11702         if(!dynamic)
11703         {
11704                 if(model->render_bih.numleafs)
11705                         bih = &model->render_bih;
11706                 else if(model->collision_bih.numleafs)
11707                         bih = &model->collision_bih;
11708         }
11709         if(bih)
11710                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11711         if(bih_triangles_count == 0)
11712                 return;
11713         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11714                 return;
11715         if(bih_triangles_count > 0)
11716         {
11717                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11718                 {
11719                         surfaceindex = bih_surfaces[triangleindex];
11720                         surface = surfaces + surfaceindex;
11721                         texture = surface->texture;
11722                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11723                                 continue;
11724                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11725                                 continue;
11726                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11727                 }
11728         }
11729         else
11730         {
11731                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11732                 {
11733                         surfaceindex = surfacelist[surfacelistindex];
11734                         surface = surfaces + surfaceindex;
11735                         // check cull box first because it rejects more than any other check
11736                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11737                                 continue;
11738                         // skip transparent surfaces
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                         numtriangles = surface->num_triangles;
11745                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11746                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11747                 }
11748         }
11749 }
11750
11751 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11752 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)
11753 {
11754         int renderentityindex;
11755         float worldmins[3];
11756         float worldmaxs[3];
11757         entity_render_t *ent;
11758
11759         if (!cl_decals_newsystem.integer)
11760                 return;
11761
11762         worldmins[0] = worldorigin[0] - worldsize;
11763         worldmins[1] = worldorigin[1] - worldsize;
11764         worldmins[2] = worldorigin[2] - worldsize;
11765         worldmaxs[0] = worldorigin[0] + worldsize;
11766         worldmaxs[1] = worldorigin[1] + worldsize;
11767         worldmaxs[2] = worldorigin[2] + worldsize;
11768
11769         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11770
11771         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11772         {
11773                 ent = r_refdef.scene.entities[renderentityindex];
11774                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11775                         continue;
11776
11777                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11778         }
11779 }
11780
11781 typedef struct r_decalsystem_splatqueue_s
11782 {
11783         vec3_t worldorigin;
11784         vec3_t worldnormal;
11785         float color[4];
11786         float tcrange[4];
11787         float worldsize;
11788         unsigned int decalsequence;
11789 }
11790 r_decalsystem_splatqueue_t;
11791
11792 int r_decalsystem_numqueued = 0;
11793 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11794
11795 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)
11796 {
11797         r_decalsystem_splatqueue_t *queue;
11798
11799         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11800                 return;
11801
11802         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11803         VectorCopy(worldorigin, queue->worldorigin);
11804         VectorCopy(worldnormal, queue->worldnormal);
11805         Vector4Set(queue->color, r, g, b, a);
11806         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11807         queue->worldsize = worldsize;
11808         queue->decalsequence = cl.decalsequence++;
11809 }
11810
11811 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11812 {
11813         int i;
11814         r_decalsystem_splatqueue_t *queue;
11815
11816         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11817                 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);
11818         r_decalsystem_numqueued = 0;
11819 }
11820
11821 extern cvar_t cl_decals_max;
11822 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11823 {
11824         int i;
11825         decalsystem_t *decalsystem = &ent->decalsystem;
11826         int numdecals;
11827         unsigned int killsequence;
11828         tridecal_t *decal;
11829         float frametime;
11830         float lifetime;
11831
11832         if (!decalsystem->numdecals)
11833                 return;
11834
11835         if (r_showsurfaces.integer)
11836                 return;
11837
11838         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11839         {
11840                 R_DecalSystem_Reset(decalsystem);
11841                 return;
11842         }
11843
11844         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11845         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11846
11847         if (decalsystem->lastupdatetime)
11848                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11849         else
11850                 frametime = 0;
11851         decalsystem->lastupdatetime = r_refdef.scene.time;
11852         numdecals = decalsystem->numdecals;
11853
11854         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11855         {
11856                 if (decal->color4f[0][3])
11857                 {
11858                         decal->lived += frametime;
11859                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11860                         {
11861                                 memset(decal, 0, sizeof(*decal));
11862                                 if (decalsystem->freedecal > i)
11863                                         decalsystem->freedecal = i;
11864                         }
11865                 }
11866         }
11867         decal = decalsystem->decals;
11868         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11869                 numdecals--;
11870
11871         // collapse the array by shuffling the tail decals into the gaps
11872         for (;;)
11873         {
11874                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11875                         decalsystem->freedecal++;
11876                 if (decalsystem->freedecal == numdecals)
11877                         break;
11878                 decal[decalsystem->freedecal] = decal[--numdecals];
11879         }
11880
11881         decalsystem->numdecals = numdecals;
11882
11883         if (numdecals <= 0)
11884         {
11885                 // if there are no decals left, reset decalsystem
11886                 R_DecalSystem_Reset(decalsystem);
11887         }
11888 }
11889
11890 extern skinframe_t *decalskinframe;
11891 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11892 {
11893         int i;
11894         decalsystem_t *decalsystem = &ent->decalsystem;
11895         int numdecals;
11896         tridecal_t *decal;
11897         float faderate;
11898         float alpha;
11899         float *v3f;
11900         float *c4f;
11901         float *t2f;
11902         const int *e;
11903         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11904         int numtris = 0;
11905
11906         numdecals = decalsystem->numdecals;
11907         if (!numdecals)
11908                 return;
11909
11910         if (r_showsurfaces.integer)
11911                 return;
11912
11913         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11914         {
11915                 R_DecalSystem_Reset(decalsystem);
11916                 return;
11917         }
11918
11919         // if the model is static it doesn't matter what value we give for
11920         // wantnormals and wanttangents, so this logic uses only rules applicable
11921         // to a model, knowing that they are meaningless otherwise
11922         RSurf_ActiveModelEntity(ent, false, false, false);
11923
11924         decalsystem->lastupdatetime = r_refdef.scene.time;
11925
11926         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11927
11928         // update vertex positions for animated models
11929         v3f = decalsystem->vertex3f;
11930         c4f = decalsystem->color4f;
11931         t2f = decalsystem->texcoord2f;
11932         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11933         {
11934                 if (!decal->color4f[0][3])
11935                         continue;
11936
11937                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11938                         continue;
11939
11940                 // skip backfaces
11941                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11942                         continue;
11943
11944                 // update color values for fading decals
11945                 if (decal->lived >= cl_decals_time.value)
11946                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11947                 else
11948                         alpha = 1.0f;
11949
11950                 c4f[ 0] = decal->color4f[0][0] * alpha;
11951                 c4f[ 1] = decal->color4f[0][1] * alpha;
11952                 c4f[ 2] = decal->color4f[0][2] * alpha;
11953                 c4f[ 3] = 1;
11954                 c4f[ 4] = decal->color4f[1][0] * alpha;
11955                 c4f[ 5] = decal->color4f[1][1] * alpha;
11956                 c4f[ 6] = decal->color4f[1][2] * alpha;
11957                 c4f[ 7] = 1;
11958                 c4f[ 8] = decal->color4f[2][0] * alpha;
11959                 c4f[ 9] = decal->color4f[2][1] * alpha;
11960                 c4f[10] = decal->color4f[2][2] * alpha;
11961                 c4f[11] = 1;
11962
11963                 t2f[0] = decal->texcoord2f[0][0];
11964                 t2f[1] = decal->texcoord2f[0][1];
11965                 t2f[2] = decal->texcoord2f[1][0];
11966                 t2f[3] = decal->texcoord2f[1][1];
11967                 t2f[4] = decal->texcoord2f[2][0];
11968                 t2f[5] = decal->texcoord2f[2][1];
11969
11970                 // update vertex positions for animated models
11971                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11972                 {
11973                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11974                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11975                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11976                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11977                 }
11978                 else
11979                 {
11980                         VectorCopy(decal->vertex3f[0], v3f);
11981                         VectorCopy(decal->vertex3f[1], v3f + 3);
11982                         VectorCopy(decal->vertex3f[2], v3f + 6);
11983                 }
11984
11985                 if (r_refdef.fogenabled)
11986                 {
11987                         alpha = RSurf_FogVertex(v3f);
11988                         VectorScale(c4f, alpha, c4f);
11989                         alpha = RSurf_FogVertex(v3f + 3);
11990                         VectorScale(c4f + 4, alpha, c4f + 4);
11991                         alpha = RSurf_FogVertex(v3f + 6);
11992                         VectorScale(c4f + 8, alpha, c4f + 8);
11993                 }
11994
11995                 v3f += 9;
11996                 c4f += 12;
11997                 t2f += 6;
11998                 numtris++;
11999         }
12000
12001         if (numtris > 0)
12002         {
12003                 r_refdef.stats[r_stat_drawndecals] += numtris;
12004
12005                 // now render the decals all at once
12006                 // (this assumes they all use one particle font texture!)
12007                 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);
12008 //              R_Mesh_ResetTextureState();
12009                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12010                 GL_DepthMask(false);
12011                 GL_DepthRange(0, 1);
12012                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12013                 GL_DepthTest(true);
12014                 GL_CullFace(GL_NONE);
12015                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12016                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12017                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12018         }
12019 }
12020
12021 static void R_DrawModelDecals(void)
12022 {
12023         int i, numdecals;
12024
12025         // fade faster when there are too many decals
12026         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12027         for (i = 0;i < r_refdef.scene.numentities;i++)
12028                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12029
12030         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12031         for (i = 0;i < r_refdef.scene.numentities;i++)
12032                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12033                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12034
12035         R_DecalSystem_ApplySplatEntitiesQueue();
12036
12037         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12038         for (i = 0;i < r_refdef.scene.numentities;i++)
12039                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12040
12041         r_refdef.stats[r_stat_totaldecals] += numdecals;
12042
12043         if (r_showsurfaces.integer)
12044                 return;
12045
12046         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12047
12048         for (i = 0;i < r_refdef.scene.numentities;i++)
12049         {
12050                 if (!r_refdef.viewcache.entityvisible[i])
12051                         continue;
12052                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12053                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12054         }
12055 }
12056
12057 extern cvar_t mod_collision_bih;
12058 static void R_DrawDebugModel(void)
12059 {
12060         entity_render_t *ent = rsurface.entity;
12061         int i, j, flagsmask;
12062         const msurface_t *surface;
12063         dp_model_t *model = ent->model;
12064
12065         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12066                 return;
12067
12068         if (r_showoverdraw.value > 0)
12069         {
12070                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12071                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12072                 R_SetupShader_Generic_NoTexture(false, false);
12073                 GL_DepthTest(false);
12074                 GL_DepthMask(false);
12075                 GL_DepthRange(0, 1);
12076                 GL_BlendFunc(GL_ONE, GL_ONE);
12077                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12078                 {
12079                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12080                                 continue;
12081                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12082                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12083                         {
12084                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12085                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12086                                 if (!rsurface.texture->currentlayers->depthmask)
12087                                         GL_Color(c, 0, 0, 1.0f);
12088                                 else if (ent == r_refdef.scene.worldentity)
12089                                         GL_Color(c, c, c, 1.0f);
12090                                 else
12091                                         GL_Color(0, c, 0, 1.0f);
12092                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12093                                 RSurf_DrawBatch();
12094                         }
12095                 }
12096                 rsurface.texture = NULL;
12097         }
12098
12099         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12100
12101 //      R_Mesh_ResetTextureState();
12102         R_SetupShader_Generic_NoTexture(false, false);
12103         GL_DepthRange(0, 1);
12104         GL_DepthTest(!r_showdisabledepthtest.integer);
12105         GL_DepthMask(false);
12106         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12107
12108         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12109         {
12110                 int triangleindex;
12111                 int bihleafindex;
12112                 qboolean cullbox = false;
12113                 const q3mbrush_t *brush;
12114                 const bih_t *bih = &model->collision_bih;
12115                 const bih_leaf_t *bihleaf;
12116                 float vertex3f[3][3];
12117                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12118                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12119                 {
12120                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12121                                 continue;
12122                         switch (bihleaf->type)
12123                         {
12124                         case BIH_BRUSH:
12125                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12126                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12127                                 {
12128                                         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);
12129                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12130                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12131                                 }
12132                                 break;
12133                         case BIH_COLLISIONTRIANGLE:
12134                                 triangleindex = bihleaf->itemindex;
12135                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12136                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12137                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12138                                 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);
12139                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12140                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12141                                 break;
12142                         case BIH_RENDERTRIANGLE:
12143                                 triangleindex = bihleaf->itemindex;
12144                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12145                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12146                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12147                                 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);
12148                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12149                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12150                                 break;
12151                         }
12152                 }
12153         }
12154
12155         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12156
12157 #ifndef USE_GLES2
12158         if (r_showtris.integer && qglPolygonMode)
12159         {
12160                 if (r_showdisabledepthtest.integer)
12161                 {
12162                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12163                         GL_DepthMask(false);
12164                 }
12165                 else
12166                 {
12167                         GL_BlendFunc(GL_ONE, GL_ZERO);
12168                         GL_DepthMask(true);
12169                 }
12170                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12171                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12172                 {
12173                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12174                                 continue;
12175                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12176                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12177                         {
12178                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12179                                 if (!rsurface.texture->currentlayers->depthmask)
12180                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12181                                 else if (ent == r_refdef.scene.worldentity)
12182                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12183                                 else
12184                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12185                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12186                                 RSurf_DrawBatch();
12187                         }
12188                 }
12189                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12190                 rsurface.texture = NULL;
12191         }
12192
12193         if (r_shownormals.value != 0 && qglBegin)
12194         {
12195                 int l, k;
12196                 vec3_t v;
12197                 if (r_showdisabledepthtest.integer)
12198                 {
12199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12200                         GL_DepthMask(false);
12201                 }
12202                 else
12203                 {
12204                         GL_BlendFunc(GL_ONE, GL_ZERO);
12205                         GL_DepthMask(true);
12206                 }
12207                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12208                 {
12209                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12210                                 continue;
12211                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12212                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12213                         {
12214                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12215                                 qglBegin(GL_LINES);
12216                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12217                                 {
12218                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12219                                         {
12220                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12221                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12222                                                 qglVertex3f(v[0], v[1], v[2]);
12223                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12224                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12225                                                 qglVertex3f(v[0], v[1], v[2]);
12226                                         }
12227                                 }
12228                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12229                                 {
12230                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12231                                         {
12232                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12233                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12234                                                 qglVertex3f(v[0], v[1], v[2]);
12235                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12236                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12237                                                 qglVertex3f(v[0], v[1], v[2]);
12238                                         }
12239                                 }
12240                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12241                                 {
12242                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12243                                         {
12244                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12245                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12246                                                 qglVertex3f(v[0], v[1], v[2]);
12247                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12248                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12249                                                 qglVertex3f(v[0], v[1], v[2]);
12250                                         }
12251                                 }
12252                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12253                                 {
12254                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12255                                         {
12256                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12257                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12258                                                 qglVertex3f(v[0], v[1], v[2]);
12259                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12260                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12261                                                 qglVertex3f(v[0], v[1], v[2]);
12262                                         }
12263                                 }
12264                                 qglEnd();
12265                                 CHECKGLERROR
12266                         }
12267                 }
12268                 rsurface.texture = NULL;
12269         }
12270 #endif
12271 }
12272
12273 int r_maxsurfacelist = 0;
12274 const msurface_t **r_surfacelist = NULL;
12275 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12276 {
12277         int i, j, endj, flagsmask;
12278         dp_model_t *model = ent->model;
12279         msurface_t *surfaces;
12280         unsigned char *update;
12281         int numsurfacelist = 0;
12282         if (model == NULL)
12283                 return;
12284
12285         if (r_maxsurfacelist < model->num_surfaces)
12286         {
12287                 r_maxsurfacelist = model->num_surfaces;
12288                 if (r_surfacelist)
12289                         Mem_Free((msurface_t **)r_surfacelist);
12290                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12291         }
12292
12293         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12294                 RSurf_ActiveModelEntity(ent, false, false, false);
12295         else if (prepass)
12296                 RSurf_ActiveModelEntity(ent, true, true, true);
12297         else if (depthonly)
12298         {
12299                 switch (vid.renderpath)
12300                 {
12301                 case RENDERPATH_GL20:
12302                 case RENDERPATH_D3D9:
12303                 case RENDERPATH_D3D10:
12304                 case RENDERPATH_D3D11:
12305                 case RENDERPATH_SOFT:
12306                 case RENDERPATH_GLES2:
12307                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12308                         break;
12309                 case RENDERPATH_GL11:
12310                 case RENDERPATH_GL13:
12311                 case RENDERPATH_GLES1:
12312                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12313                         break;
12314                 }
12315         }
12316         else
12317         {
12318                 switch (vid.renderpath)
12319                 {
12320                 case RENDERPATH_GL20:
12321                 case RENDERPATH_D3D9:
12322                 case RENDERPATH_D3D10:
12323                 case RENDERPATH_D3D11:
12324                 case RENDERPATH_SOFT:
12325                 case RENDERPATH_GLES2:
12326                         RSurf_ActiveModelEntity(ent, true, true, false);
12327                         break;
12328                 case RENDERPATH_GL11:
12329                 case RENDERPATH_GL13:
12330                 case RENDERPATH_GLES1:
12331                         RSurf_ActiveModelEntity(ent, true, false, false);
12332                         break;
12333                 }
12334         }
12335
12336         surfaces = model->data_surfaces;
12337         update = model->brushq1.lightmapupdateflags;
12338
12339         // update light styles
12340         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12341         {
12342                 model_brush_lightstyleinfo_t *style;
12343                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12344                 {
12345                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12346                         {
12347                                 int *list = style->surfacelist;
12348                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12349                                 for (j = 0;j < style->numsurfaces;j++)
12350                                         update[list[j]] = true;
12351                         }
12352                 }
12353         }
12354
12355         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12356
12357         if (debug)
12358         {
12359                 R_DrawDebugModel();
12360                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12361                 return;
12362         }
12363
12364         rsurface.lightmaptexture = NULL;
12365         rsurface.deluxemaptexture = NULL;
12366         rsurface.uselightmaptexture = false;
12367         rsurface.texture = NULL;
12368         rsurface.rtlight = NULL;
12369         numsurfacelist = 0;
12370         // add visible surfaces to draw list
12371         if (ent == r_refdef.scene.worldentity)
12372         {
12373                 // for the world entity, check surfacevisible
12374                 for (i = 0;i < model->nummodelsurfaces;i++)
12375                 {
12376                         j = model->sortedmodelsurfaces[i];
12377                         if (r_refdef.viewcache.world_surfacevisible[j])
12378                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12379                 }
12380         }
12381         else
12382         {
12383                 // add all surfaces
12384                 for (i = 0; i < model->nummodelsurfaces; i++)
12385                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12386         }
12387         // don't do anything if there were no surfaces
12388         if (!numsurfacelist)
12389         {
12390                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12391                 return;
12392         }
12393         // update lightmaps if needed
12394         if (update)
12395         {
12396                 int updated = 0;
12397                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12398                 {
12399                         if (update[j])
12400                         {
12401                                 updated++;
12402                                 R_BuildLightMap(ent, surfaces + j);
12403                         }
12404                 }
12405         }
12406
12407         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12408
12409         // add to stats if desired
12410         if (r_speeds.integer && !skysurfaces && !depthonly)
12411         {
12412                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12413                 for (j = 0;j < numsurfacelist;j++)
12414                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12415         }
12416
12417         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12418 }
12419
12420 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12421 {
12422         int q;
12423         static texture_t texture;
12424         static msurface_t surface;
12425         const msurface_t *surfacelist = &surface;
12426
12427         // fake enough texture and surface state to render this geometry
12428
12429         texture.update_lastrenderframe = -1; // regenerate this texture
12430         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12431         texture.basealpha = 1.0f;
12432         texture.currentskinframe = skinframe;
12433         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12434         texture.offsetmapping = OFFSETMAPPING_OFF;
12435         texture.offsetscale = 1;
12436         texture.specularscalemod = 1;
12437         texture.specularpowermod = 1;
12438         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12439         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12440         // JUST GREP FOR "specularscalemod = 1".
12441
12442         for (q = 0; q < 3; q++)
12443         {
12444                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12445                 texture.render_modellight_lightdir[q] = q == 2;
12446                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12447                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12448                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12449                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12450                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12451                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12452                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12453                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12454         }
12455         texture.currentalpha = 1.0f;
12456
12457         surface.texture = &texture;
12458         surface.num_triangles = numtriangles;
12459         surface.num_firsttriangle = firsttriangle;
12460         surface.num_vertices = numvertices;
12461         surface.num_firstvertex = firstvertex;
12462
12463         // now render it
12464         rsurface.texture = R_GetCurrentTexture(surface.texture);
12465         rsurface.lightmaptexture = NULL;
12466         rsurface.deluxemaptexture = NULL;
12467         rsurface.uselightmaptexture = false;
12468         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12469 }
12470
12471 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)
12472 {
12473         static msurface_t surface;
12474         const msurface_t *surfacelist = &surface;
12475
12476         // fake enough texture and surface state to render this geometry
12477         surface.texture = texture;
12478         surface.num_triangles = numtriangles;
12479         surface.num_firsttriangle = firsttriangle;
12480         surface.num_vertices = numvertices;
12481         surface.num_firstvertex = firstvertex;
12482
12483         // now render it
12484         rsurface.texture = R_GetCurrentTexture(surface.texture);
12485         rsurface.lightmaptexture = NULL;
12486         rsurface.deluxemaptexture = NULL;
12487         rsurface.uselightmaptexture = false;
12488         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12489 }