]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix incorrect layer color values that caused models to be completely black in RENDERP...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
83
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
97 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
104 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
105 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 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)"};
115 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)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 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"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
122
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
126
127 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"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 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"};
131 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"};
132
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 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."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 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."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 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."};
144 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."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 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"};
147 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"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 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"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 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
158 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
159
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
168
169 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)"};
170 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"};
171
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
175
176 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"};
177 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"};
178 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
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
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
221
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
224
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
231
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
242
243 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"};
244
245 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"};
246
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
248
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
250
251 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)"};
252 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)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
255
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 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"};
258
259 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."};
260
261 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)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
263 {
264         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
268 };
269
270 extern cvar_t v_glslgamma_2d;
271
272 extern qboolean v_flipped_state;
273
274 r_framebufferstate_t r_fb;
275
276 /// shadow volume bsp struct with automatically growing nodes buffer
277 svbsp_t r_svbsp;
278
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
280
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
294
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
297 {
298         char basename[64];
299         rtexture_t *texture;
300 }
301 cubemapinfo_t;
302
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
305
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
309
310 typedef struct r_qwskincache_s
311 {
312         char name[MAX_QPATH];
313         skinframe_t *skinframe;
314 }
315 r_qwskincache_t;
316
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
319
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 const float r_screenvertex3f[12] =
323 {
324         0, 0, 0,
325         1, 0, 0,
326         1, 1, 0,
327         0, 1, 0
328 };
329
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
331 {
332         int i;
333         for (i = 0;i < verts;i++)
334         {
335                 out[0] = in[0] * r;
336                 out[1] = in[1] * g;
337                 out[2] = in[2] * b;
338                 out[3] = in[3];
339                 in += 4;
340                 out += 4;
341         }
342 }
343
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
345 {
346         int i;
347         for (i = 0;i < verts;i++)
348         {
349                 out[0] = r;
350                 out[1] = g;
351                 out[2] = b;
352                 out[3] = a;
353                 out += 4;
354         }
355 }
356
357 // FIXME: move this to client?
358 void FOG_clear(void)
359 {
360         if (gamemode == GAME_NEHAHRA)
361         {
362                 Cvar_Set("gl_fogenable", "0");
363                 Cvar_Set("gl_fogdensity", "0.2");
364                 Cvar_Set("gl_fogred", "0.3");
365                 Cvar_Set("gl_foggreen", "0.3");
366                 Cvar_Set("gl_fogblue", "0.3");
367         }
368         r_refdef.fog_density = 0;
369         r_refdef.fog_red = 0;
370         r_refdef.fog_green = 0;
371         r_refdef.fog_blue = 0;
372         r_refdef.fog_alpha = 1;
373         r_refdef.fog_start = 0;
374         r_refdef.fog_end = 16384;
375         r_refdef.fog_height = 1<<30;
376         r_refdef.fog_fadedepth = 128;
377         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
378 }
379
380 static void R_BuildBlankTextures(void)
381 {
382         unsigned char data[4];
383         data[2] = 128; // normal X
384         data[1] = 128; // normal Y
385         data[0] = 255; // normal Z
386         data[3] = 255; // height
387         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 255;
389         data[1] = 255;
390         data[2] = 255;
391         data[3] = 255;
392         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393         data[0] = 128;
394         data[1] = 128;
395         data[2] = 128;
396         data[3] = 255;
397         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 0;
399         data[1] = 0;
400         data[2] = 0;
401         data[3] = 255;
402         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNoTexture(void)
406 {
407         int x, y;
408         unsigned char pix[16][16][4];
409         // this makes a light grey/dark grey checkerboard texture
410         for (y = 0;y < 16;y++)
411         {
412                 for (x = 0;x < 16;x++)
413                 {
414                         if ((y < 8) ^ (x < 8))
415                         {
416                                 pix[y][x][0] = 128;
417                                 pix[y][x][1] = 128;
418                                 pix[y][x][2] = 128;
419                                 pix[y][x][3] = 255;
420                         }
421                         else
422                         {
423                                 pix[y][x][0] = 64;
424                                 pix[y][x][1] = 64;
425                                 pix[y][x][2] = 64;
426                                 pix[y][x][3] = 255;
427                         }
428                 }
429         }
430         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildWhiteCube(void)
434 {
435         unsigned char data[6*1*1*4];
436         memset(data, 255, sizeof(data));
437         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
438 }
439
440 static void R_BuildNormalizationCube(void)
441 {
442         int x, y, side;
443         vec3_t v;
444         vec_t s, t, intensity;
445 #define NORMSIZE 64
446         unsigned char *data;
447         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448         for (side = 0;side < 6;side++)
449         {
450                 for (y = 0;y < NORMSIZE;y++)
451                 {
452                         for (x = 0;x < NORMSIZE;x++)
453                         {
454                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
456                                 switch(side)
457                                 {
458                                 default:
459                                 case 0:
460                                         v[0] = 1;
461                                         v[1] = -t;
462                                         v[2] = -s;
463                                         break;
464                                 case 1:
465                                         v[0] = -1;
466                                         v[1] = -t;
467                                         v[2] = s;
468                                         break;
469                                 case 2:
470                                         v[0] = s;
471                                         v[1] = 1;
472                                         v[2] = t;
473                                         break;
474                                 case 3:
475                                         v[0] = s;
476                                         v[1] = -1;
477                                         v[2] = -t;
478                                         break;
479                                 case 4:
480                                         v[0] = s;
481                                         v[1] = -t;
482                                         v[2] = 1;
483                                         break;
484                                 case 5:
485                                         v[0] = -s;
486                                         v[1] = -t;
487                                         v[2] = -1;
488                                         break;
489                                 }
490                                 intensity = 127.0f / sqrt(DotProduct(v, v));
491                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494                                 data[((side*64+y)*64+x)*4+3] = 255;
495                         }
496                 }
497         }
498         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499         Mem_Free(data);
500 }
501
502 static void R_BuildFogTexture(void)
503 {
504         int x, b;
505 #define FOGWIDTH 256
506         unsigned char data1[FOGWIDTH][4];
507         //unsigned char data2[FOGWIDTH][4];
508         double d, r, alpha;
509
510         r_refdef.fogmasktable_start = r_refdef.fog_start;
511         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512         r_refdef.fogmasktable_range = r_refdef.fogrange;
513         r_refdef.fogmasktable_density = r_refdef.fog_density;
514
515         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
517         {
518                 d = (x * r - r_refdef.fogmasktable_start);
519                 if(developer_extra.integer)
520                         Con_DPrintf("%f ", d);
521                 d = max(0, d);
522                 if (r_fog_exp2.integer)
523                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
524                 else
525                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526                 if(developer_extra.integer)
527                         Con_DPrintf(" : %f ", alpha);
528                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529                 if(developer_extra.integer)
530                         Con_DPrintf(" = %f\n", alpha);
531                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
532         }
533
534         for (x = 0;x < FOGWIDTH;x++)
535         {
536                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537                 data1[x][0] = b;
538                 data1[x][1] = b;
539                 data1[x][2] = b;
540                 data1[x][3] = 255;
541                 //data2[x][0] = 255 - b;
542                 //data2[x][1] = 255 - b;
543                 //data2[x][2] = 255 - b;
544                 //data2[x][3] = 255;
545         }
546         if (r_texture_fogattenuation)
547         {
548                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
550         }
551         else
552         {
553                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
555         }
556 }
557
558 static void R_BuildFogHeightTexture(void)
559 {
560         unsigned char *inpixels;
561         int size;
562         int x;
563         int y;
564         int j;
565         float c[4];
566         float f;
567         inpixels = NULL;
568         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569         if (r_refdef.fogheighttexturename[0])
570                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
571         if (!inpixels)
572         {
573                 r_refdef.fog_height_tablesize = 0;
574                 if (r_texture_fogheighttexture)
575                         R_FreeTexture(r_texture_fogheighttexture);
576                 r_texture_fogheighttexture = NULL;
577                 if (r_refdef.fog_height_table2d)
578                         Mem_Free(r_refdef.fog_height_table2d);
579                 r_refdef.fog_height_table2d = NULL;
580                 if (r_refdef.fog_height_table1d)
581                         Mem_Free(r_refdef.fog_height_table1d);
582                 r_refdef.fog_height_table1d = NULL;
583                 return;
584         }
585         size = image_width;
586         r_refdef.fog_height_tablesize = size;
587         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
590         Mem_Free(inpixels);
591         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
592         // average fog color table accounting for every fog layer between a point
593         // and the camera.  (Note: attenuation is handled separately!)
594         for (y = 0;y < size;y++)
595         {
596                 for (x = 0;x < size;x++)
597                 {
598                         Vector4Clear(c);
599                         f = 0;
600                         if (x < y)
601                         {
602                                 for (j = x;j <= y;j++)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         else
609                         {
610                                 for (j = x;j >= y;j--)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         f = 1.0f / f;
617                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
621                 }
622         }
623         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
624 }
625
626 //=======================================================================================================================================================
627
628 static const char *builtinshaderstrings[] =
629 {
630 #include "shader_glsl.h"
631 0
632 };
633
634 const char *builtinhlslshaderstrings[] =
635 {
636 #include "shader_hlsl.h"
637 0
638 };
639
640 //=======================================================================================================================================================
641
642 typedef struct shaderpermutationinfo_s
643 {
644         const char *pretext;
645         const char *name;
646 }
647 shaderpermutationinfo_t;
648
649 typedef struct shadermodeinfo_s
650 {
651         const char *sourcebasename;
652         const char *extension;
653         const char **builtinshaderstrings;
654         const char *pretext;
655         const char *name;
656         char *filename;
657         char *builtinstring;
658         int builtincrc;
659 }
660 shadermodeinfo_t;
661
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
664 {
665         {"#define USEDIFFUSE\n", " diffuse"},
666         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
667         {"#define USEVIEWTINT\n", " viewtint"},
668         {"#define USECOLORMAPPING\n", " colormapping"},
669         {"#define USESATURATION\n", " saturation"},
670         {"#define USEFOGINSIDE\n", " foginside"},
671         {"#define USEFOGOUTSIDE\n", " fogoutside"},
672         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
673         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
674         {"#define USEGAMMARAMPS\n", " gammaramps"},
675         {"#define USECUBEFILTER\n", " cubefilter"},
676         {"#define USEGLOW\n", " glow"},
677         {"#define USEBLOOM\n", " bloom"},
678         {"#define USESPECULAR\n", " specular"},
679         {"#define USEPOSTPROCESSING\n", " postprocessing"},
680         {"#define USEREFLECTION\n", " reflection"},
681         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
682         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
683         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
684         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
685         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
686         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
687         {"#define USEALPHAKILL\n", " alphakill"},
688         {"#define USEREFLECTCUBE\n", " reflectcube"},
689         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
690         {"#define USEBOUNCEGRID\n", " bouncegrid"},
691         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
692         {"#define USETRIPPY\n", " trippy"},
693         {"#define USEDEPTHRGB\n", " depthrgb"},
694         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
695         {"#define USESKELETAL\n", " skeletal"},
696         {"#define USEOCCLUDE\n", " occlude"}
697 };
698
699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
700 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
701 {
702         // SHADERLANGUAGE_GLSL
703         {
704                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
705                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721         },
722         // SHADERLANGUAGE_HLSL
723         {
724                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
725                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
726                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
727                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
741         },
742 };
743
744 struct r_glsl_permutation_s;
745 typedef struct r_glsl_permutation_s
746 {
747         /// hash lookup data
748         struct r_glsl_permutation_s *hashnext;
749         unsigned int mode;
750         dpuint64 permutation;
751
752         /// indicates if we have tried compiling this permutation already
753         qboolean compiled;
754         /// 0 if compilation failed
755         int program;
756         // texture units assigned to each detected uniform
757         int tex_Texture_First;
758         int tex_Texture_Second;
759         int tex_Texture_GammaRamps;
760         int tex_Texture_Normal;
761         int tex_Texture_Color;
762         int tex_Texture_Gloss;
763         int tex_Texture_Glow;
764         int tex_Texture_SecondaryNormal;
765         int tex_Texture_SecondaryColor;
766         int tex_Texture_SecondaryGloss;
767         int tex_Texture_SecondaryGlow;
768         int tex_Texture_Pants;
769         int tex_Texture_Shirt;
770         int tex_Texture_FogHeightTexture;
771         int tex_Texture_FogMask;
772         int tex_Texture_Lightmap;
773         int tex_Texture_Deluxemap;
774         int tex_Texture_Attenuation;
775         int tex_Texture_Cube;
776         int tex_Texture_Refraction;
777         int tex_Texture_Reflection;
778         int tex_Texture_ShadowMap2D;
779         int tex_Texture_CubeProjection;
780         int tex_Texture_ScreenNormalMap;
781         int tex_Texture_ScreenDiffuse;
782         int tex_Texture_ScreenSpecular;
783         int tex_Texture_ReflectMask;
784         int tex_Texture_ReflectCube;
785         int tex_Texture_BounceGrid;
786         /// locations of detected uniforms in program object, or -1 if not found
787         int loc_Texture_First;
788         int loc_Texture_Second;
789         int loc_Texture_GammaRamps;
790         int loc_Texture_Normal;
791         int loc_Texture_Color;
792         int loc_Texture_Gloss;
793         int loc_Texture_Glow;
794         int loc_Texture_SecondaryNormal;
795         int loc_Texture_SecondaryColor;
796         int loc_Texture_SecondaryGloss;
797         int loc_Texture_SecondaryGlow;
798         int loc_Texture_Pants;
799         int loc_Texture_Shirt;
800         int loc_Texture_FogHeightTexture;
801         int loc_Texture_FogMask;
802         int loc_Texture_Lightmap;
803         int loc_Texture_Deluxemap;
804         int loc_Texture_Attenuation;
805         int loc_Texture_Cube;
806         int loc_Texture_Refraction;
807         int loc_Texture_Reflection;
808         int loc_Texture_ShadowMap2D;
809         int loc_Texture_CubeProjection;
810         int loc_Texture_ScreenNormalMap;
811         int loc_Texture_ScreenDiffuse;
812         int loc_Texture_ScreenSpecular;
813         int loc_Texture_ReflectMask;
814         int loc_Texture_ReflectCube;
815         int loc_Texture_BounceGrid;
816         int loc_Alpha;
817         int loc_BloomBlur_Parameters;
818         int loc_ClientTime;
819         int loc_Color_Ambient;
820         int loc_Color_Diffuse;
821         int loc_Color_Specular;
822         int loc_Color_Glow;
823         int loc_Color_Pants;
824         int loc_Color_Shirt;
825         int loc_DeferredColor_Ambient;
826         int loc_DeferredColor_Diffuse;
827         int loc_DeferredColor_Specular;
828         int loc_DeferredMod_Diffuse;
829         int loc_DeferredMod_Specular;
830         int loc_DistortScaleRefractReflect;
831         int loc_EyePosition;
832         int loc_FogColor;
833         int loc_FogHeightFade;
834         int loc_FogPlane;
835         int loc_FogPlaneViewDist;
836         int loc_FogRangeRecip;
837         int loc_LightColor;
838         int loc_LightDir;
839         int loc_LightPosition;
840         int loc_OffsetMapping_ScaleSteps;
841         int loc_OffsetMapping_LodDistance;
842         int loc_OffsetMapping_Bias;
843         int loc_PixelSize;
844         int loc_ReflectColor;
845         int loc_ReflectFactor;
846         int loc_ReflectOffset;
847         int loc_RefractColor;
848         int loc_Saturation;
849         int loc_ScreenCenterRefractReflect;
850         int loc_ScreenScaleRefractReflect;
851         int loc_ScreenToDepth;
852         int loc_ShadowMap_Parameters;
853         int loc_ShadowMap_TextureScale;
854         int loc_SpecularPower;
855         int loc_Skeletal_Transform12;
856         int loc_UserVec1;
857         int loc_UserVec2;
858         int loc_UserVec3;
859         int loc_UserVec4;
860         int loc_ViewTintColor;
861         int loc_ViewToLight;
862         int loc_ModelToLight;
863         int loc_TexMatrix;
864         int loc_BackgroundTexMatrix;
865         int loc_ModelViewProjectionMatrix;
866         int loc_ModelViewMatrix;
867         int loc_PixelToScreenTexCoord;
868         int loc_ModelToReflectCube;
869         int loc_ShadowMapMatrix;
870         int loc_BloomColorSubtract;
871         int loc_NormalmapScrollBlend;
872         int loc_BounceGridMatrix;
873         int loc_BounceGridIntensity;
874         /// uniform block bindings
875         int ubibind_Skeletal_Transform12_UniformBlock;
876         /// uniform block indices
877         int ubiloc_Skeletal_Transform12_UniformBlock;
878 }
879 r_glsl_permutation_t;
880
881 #define SHADERPERMUTATION_HASHSIZE 256
882
883
884 // non-degradable "lightweight" shader parameters to keep the permutations simpler
885 // these can NOT degrade! only use for simple stuff
886 enum
887 {
888         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
889         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
890         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
891         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
892         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
893         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
894         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
895         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
896         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
897         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
898         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
899         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
900         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
901         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
902 };
903 #define SHADERSTATICPARMS_COUNT 14
904
905 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
906 static int shaderstaticparms_count = 0;
907
908 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
909 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
910
911 extern qboolean r_shadow_shadowmapsampler;
912 extern int r_shadow_shadowmappcf;
913 qboolean R_CompileShader_CheckStaticParms(void)
914 {
915         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
916         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
917         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
918
919         // detect all
920         if (r_glsl_saturation_redcompensate.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
922         if (r_glsl_vertextextureblend_usebothalphas.integer)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
924         if (r_shadow_glossexact.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
926         if (r_glsl_postprocess.integer)
927         {
928                 if (r_glsl_postprocess_uservec1_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
930                 if (r_glsl_postprocess_uservec2_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
932                 if (r_glsl_postprocess_uservec3_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
934                 if (r_glsl_postprocess_uservec4_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
936         }
937         if (r_fxaa.integer)
938                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
939         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
940                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
941
942         if (r_shadow_shadowmapsampler)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
944         if (r_shadow_shadowmappcf > 1)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
946         else if (r_shadow_shadowmappcf)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
948         if (r_celshading.integer)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
950         if (r_celoutlines.integer)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
952
953         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
954 }
955
956 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
957         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
958                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
959         else \
960                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
961 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
962 {
963         shaderstaticparms_count = 0;
964
965         // emit all
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
980 }
981
982 /// information about each possible shader permutation
983 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
984 /// currently selected permutation
985 r_glsl_permutation_t *r_glsl_permutation;
986 /// storage for permutations linked in the hash table
987 memexpandablearray_t r_glsl_permutationarray;
988
989 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
990 {
991         //unsigned int hashdepth = 0;
992         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
993         r_glsl_permutation_t *p;
994         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
995         {
996                 if (p->mode == mode && p->permutation == permutation)
997                 {
998                         //if (hashdepth > 10)
999                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1000                         return p;
1001                 }
1002                 //hashdepth++;
1003         }
1004         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1005         p->mode = mode;
1006         p->permutation = permutation;
1007         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1008         r_glsl_permutationhash[mode][hashindex] = p;
1009         //if (hashdepth > 10)
1010         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1011         return p;
1012 }
1013
1014 static char *R_ShaderStrCat(const char **strings)
1015 {
1016         char *string, *s;
1017         const char **p = strings;
1018         const char *t;
1019         size_t len = 0;
1020         for (p = strings;(t = *p);p++)
1021                 len += strlen(t);
1022         len++;
1023         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1024         len = 0;
1025         for (p = strings;(t = *p);p++)
1026         {
1027                 len = strlen(t);
1028                 memcpy(s, t, len);
1029                 s += len;
1030         }
1031         *s = 0;
1032         return string;
1033 }
1034
1035 static char *R_ShaderStrCat(const char **strings);
1036 static void R_InitShaderModeInfo(void)
1037 {
1038         int i, language;
1039         shadermodeinfo_t *modeinfo;
1040         // 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)
1041         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1042         {
1043                 for (i = 0; i < SHADERMODE_COUNT; i++)
1044                 {
1045                         char filename[MAX_QPATH];
1046                         modeinfo = &shadermodeinfo[language][i];
1047                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1048                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1049                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1050                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1051                 }
1052         }
1053 }
1054
1055 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1056 {
1057         char *shaderstring;
1058         // if the mode has no filename we have to return the builtin string
1059         if (builtinonly || !modeinfo->filename)
1060                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1061         // note that FS_LoadFile appends a 0 byte to make it a valid string
1062         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1063         if (shaderstring)
1064         {
1065                 if (printfromdisknotice)
1066                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1067                 return shaderstring;
1068         }
1069         // fall back to builtinstring
1070         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071 }
1072
1073 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1074 {
1075         int i;
1076         int ubibind;
1077         int sampler;
1078         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1079         char *sourcestring;
1080         char permutationname[256];
1081         int vertstrings_count = 0;
1082         int geomstrings_count = 0;
1083         int fragstrings_count = 0;
1084         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1086         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1087
1088         if (p->compiled)
1089                 return;
1090         p->compiled = true;
1091         p->program = 0;
1092
1093         permutationname[0] = 0;
1094         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1095
1096         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1097
1098         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1099         if(vid.support.glshaderversion >= 140)
1100         {
1101                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1102                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1103                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1104                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1105                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1106                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1107         }
1108         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1109         else if(vid.support.glshaderversion >= 130)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1117         }
1118         // if we can do #version 120, we should (this adds the invariant keyword)
1119         else if(vid.support.glshaderversion >= 120)
1120         {
1121                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1122                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1123                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1124                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1125                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1126                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1127         }
1128         // GLES also adds several things from GLSL120
1129         switch(vid.renderpath)
1130         {
1131         case RENDERPATH_GLES2:
1132                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1133                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1134                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1135                 break;
1136         default:
1137                 break;
1138         }
1139
1140         // the first pretext is which type of shader to compile as
1141         // (later these will all be bound together as a program object)
1142         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1143         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1144         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1145
1146         // the second pretext is the mode (for example a light source)
1147         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1148         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1149         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1150         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1151
1152         // now add all the permutation pretexts
1153         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1154         {
1155                 if (permutation & (1ll<<i))
1156                 {
1157                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1158                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1159                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1160                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1161                 }
1162                 else
1163                 {
1164                         // keep line numbers correct
1165                         vertstrings_list[vertstrings_count++] = "\n";
1166                         geomstrings_list[geomstrings_count++] = "\n";
1167                         fragstrings_list[fragstrings_count++] = "\n";
1168                 }
1169         }
1170
1171         // add static parms
1172         R_CompileShader_AddStaticParms(mode, permutation);
1173         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1174         vertstrings_count += shaderstaticparms_count;
1175         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176         geomstrings_count += shaderstaticparms_count;
1177         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         fragstrings_count += shaderstaticparms_count;
1179
1180         // now append the shader text itself
1181         vertstrings_list[vertstrings_count++] = sourcestring;
1182         geomstrings_list[geomstrings_count++] = sourcestring;
1183         fragstrings_list[fragstrings_count++] = sourcestring;
1184
1185         // compile the shader program
1186         if (vertstrings_count + geomstrings_count + fragstrings_count)
1187                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1188         if (p->program)
1189         {
1190                 CHECKGLERROR
1191                 qglUseProgram(p->program);CHECKGLERROR
1192                 // look up all the uniform variable names we care about, so we don't
1193                 // have to look them up every time we set them
1194
1195 #if 0
1196                 // debugging aid
1197                 {
1198                         GLint activeuniformindex = 0;
1199                         GLint numactiveuniforms = 0;
1200                         char uniformname[128];
1201                         GLsizei uniformnamelength = 0;
1202                         GLint uniformsize = 0;
1203                         GLenum uniformtype = 0;
1204                         memset(uniformname, 0, sizeof(uniformname));
1205                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1206                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1207                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1208                         {
1209                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1210                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1211                         }
1212                 }
1213 #endif
1214
1215                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1216                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1217                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1218                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1219                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1220                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1221                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1222                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1223                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1224                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1225                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1226                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1227                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1228                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1229                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1230                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1231                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1232                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1233                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1234                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1235                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1236                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1237                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1238                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1239                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1240                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1241                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1242                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1243                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1244                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1245                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1246                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1247                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1248                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1249                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1250                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1251                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1252                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1253                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1254                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1255                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1256                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1257                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1258                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1259                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1260                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1261                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1262                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1263                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1264                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1265                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1266                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1267                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1268                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1269                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1270                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1271                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1272                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1273                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1274                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1275                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1276                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1277                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1278                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1279                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1280                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1281                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1282                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1283                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1284                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1285                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1286                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1287                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1288                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1289                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1290                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1291                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1292                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1293                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1294                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1295                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1296                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1297                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1298                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1299                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1300                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1301                 // initialize the samplers to refer to the texture units we use
1302                 p->tex_Texture_First = -1;
1303                 p->tex_Texture_Second = -1;
1304                 p->tex_Texture_GammaRamps = -1;
1305                 p->tex_Texture_Normal = -1;
1306                 p->tex_Texture_Color = -1;
1307                 p->tex_Texture_Gloss = -1;
1308                 p->tex_Texture_Glow = -1;
1309                 p->tex_Texture_SecondaryNormal = -1;
1310                 p->tex_Texture_SecondaryColor = -1;
1311                 p->tex_Texture_SecondaryGloss = -1;
1312                 p->tex_Texture_SecondaryGlow = -1;
1313                 p->tex_Texture_Pants = -1;
1314                 p->tex_Texture_Shirt = -1;
1315                 p->tex_Texture_FogHeightTexture = -1;
1316                 p->tex_Texture_FogMask = -1;
1317                 p->tex_Texture_Lightmap = -1;
1318                 p->tex_Texture_Deluxemap = -1;
1319                 p->tex_Texture_Attenuation = -1;
1320                 p->tex_Texture_Cube = -1;
1321                 p->tex_Texture_Refraction = -1;
1322                 p->tex_Texture_Reflection = -1;
1323                 p->tex_Texture_ShadowMap2D = -1;
1324                 p->tex_Texture_CubeProjection = -1;
1325                 p->tex_Texture_ScreenNormalMap = -1;
1326                 p->tex_Texture_ScreenDiffuse = -1;
1327                 p->tex_Texture_ScreenSpecular = -1;
1328                 p->tex_Texture_ReflectMask = -1;
1329                 p->tex_Texture_ReflectCube = -1;
1330                 p->tex_Texture_BounceGrid = -1;
1331                 // bind the texture samplers in use
1332                 sampler = 0;
1333                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1334                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1335                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1336                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1337                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1338                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1339                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1340                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1341                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1342                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1343                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1344                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1345                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1346                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1347                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1348                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1349                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1350                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1351                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1352                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1353                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1354                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1355                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1356                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1357                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1358                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1359                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1360                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1361                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1362                 // get the uniform block indices so we can bind them
1363 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1364                 if (vid.support.arb_uniform_buffer_object)
1365                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1366                 else
1367 #endif
1368                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1369                 // clear the uniform block bindings
1370                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1371                 // bind the uniform blocks in use
1372                 ubibind = 0;
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1375 #endif
1376                 // we're done compiling and setting up the shader, at least until it is used
1377                 CHECKGLERROR
1378                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1379         }
1380         else
1381                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1382
1383         // free the strings
1384         if (sourcestring)
1385                 Mem_Free(sourcestring);
1386 }
1387
1388 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1389 {
1390         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1391         if (r_glsl_permutation != perm)
1392         {
1393                 r_glsl_permutation = perm;
1394                 if (!r_glsl_permutation->program)
1395                 {
1396                         if (!r_glsl_permutation->compiled)
1397                         {
1398                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1399                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1400                         }
1401                         if (!r_glsl_permutation->program)
1402                         {
1403                                 // remove features until we find a valid permutation
1404                                 int i;
1405                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1406                                 {
1407                                         // reduce i more quickly whenever it would not remove any bits
1408                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1409                                         if (!(permutation & j))
1410                                                 continue;
1411                                         permutation -= j;
1412                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1413                                         if (!r_glsl_permutation->compiled)
1414                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1415                                         if (r_glsl_permutation->program)
1416                                                 break;
1417                                 }
1418                                 if (i >= SHADERPERMUTATION_COUNT)
1419                                 {
1420                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1421                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422                                         qglUseProgram(0);CHECKGLERROR
1423                                         return; // no bit left to clear, entire mode is broken
1424                                 }
1425                         }
1426                 }
1427                 CHECKGLERROR
1428                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1429         }
1430         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1431         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1432         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1433         CHECKGLERROR
1434 }
1435
1436 #ifdef SUPPORTD3D
1437
1438 #ifdef SUPPORTD3D
1439 #include <d3d9.h>
1440 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1441 extern D3DCAPS9 vid_d3d9caps;
1442 #endif
1443
1444 struct r_hlsl_permutation_s;
1445 typedef struct r_hlsl_permutation_s
1446 {
1447         /// hash lookup data
1448         struct r_hlsl_permutation_s *hashnext;
1449         unsigned int mode;
1450         dpuint64 permutation;
1451
1452         /// indicates if we have tried compiling this permutation already
1453         qboolean compiled;
1454         /// NULL if compilation failed
1455         IDirect3DVertexShader9 *vertexshader;
1456         IDirect3DPixelShader9 *pixelshader;
1457 }
1458 r_hlsl_permutation_t;
1459
1460 typedef enum D3DVSREGISTER_e
1461 {
1462         D3DVSREGISTER_TexMatrix = 0, // float4x4
1463         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1464         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1465         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1466         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1467         D3DVSREGISTER_ModelToLight = 20, // float4x4
1468         D3DVSREGISTER_EyePosition = 24,
1469         D3DVSREGISTER_FogPlane = 25,
1470         D3DVSREGISTER_LightDir = 26,
1471         D3DVSREGISTER_LightPosition = 27,
1472 }
1473 D3DVSREGISTER_t;
1474
1475 typedef enum D3DPSREGISTER_e
1476 {
1477         D3DPSREGISTER_Alpha = 0,
1478         D3DPSREGISTER_BloomBlur_Parameters = 1,
1479         D3DPSREGISTER_ClientTime = 2,
1480         D3DPSREGISTER_Color_Ambient = 3,
1481         D3DPSREGISTER_Color_Diffuse = 4,
1482         D3DPSREGISTER_Color_Specular = 5,
1483         D3DPSREGISTER_Color_Glow = 6,
1484         D3DPSREGISTER_Color_Pants = 7,
1485         D3DPSREGISTER_Color_Shirt = 8,
1486         D3DPSREGISTER_DeferredColor_Ambient = 9,
1487         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1488         D3DPSREGISTER_DeferredColor_Specular = 11,
1489         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1490         D3DPSREGISTER_DeferredMod_Specular = 13,
1491         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1492         D3DPSREGISTER_EyePosition = 15, // unused
1493         D3DPSREGISTER_FogColor = 16,
1494         D3DPSREGISTER_FogHeightFade = 17,
1495         D3DPSREGISTER_FogPlane = 18,
1496         D3DPSREGISTER_FogPlaneViewDist = 19,
1497         D3DPSREGISTER_FogRangeRecip = 20,
1498         D3DPSREGISTER_LightColor = 21,
1499         D3DPSREGISTER_LightDir = 22, // unused
1500         D3DPSREGISTER_LightPosition = 23,
1501         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1502         D3DPSREGISTER_PixelSize = 25,
1503         D3DPSREGISTER_ReflectColor = 26,
1504         D3DPSREGISTER_ReflectFactor = 27,
1505         D3DPSREGISTER_ReflectOffset = 28,
1506         D3DPSREGISTER_RefractColor = 29,
1507         D3DPSREGISTER_Saturation = 30,
1508         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1509         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1510         D3DPSREGISTER_ScreenToDepth = 33,
1511         D3DPSREGISTER_ShadowMap_Parameters = 34,
1512         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1513         D3DPSREGISTER_SpecularPower = 36,
1514         D3DPSREGISTER_UserVec1 = 37,
1515         D3DPSREGISTER_UserVec2 = 38,
1516         D3DPSREGISTER_UserVec3 = 39,
1517         D3DPSREGISTER_UserVec4 = 40,
1518         D3DPSREGISTER_ViewTintColor = 41,
1519         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1520         D3DPSREGISTER_BloomColorSubtract = 43,
1521         D3DPSREGISTER_ViewToLight = 44, // float4x4
1522         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1523         D3DPSREGISTER_NormalmapScrollBlend = 52,
1524         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1525         D3DPSREGISTER_OffsetMapping_Bias = 54,
1526         // next at 54
1527 }
1528 D3DPSREGISTER_t;
1529
1530 /// information about each possible shader permutation
1531 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1532 /// currently selected permutation
1533 r_hlsl_permutation_t *r_hlsl_permutation;
1534 /// storage for permutations linked in the hash table
1535 memexpandablearray_t r_hlsl_permutationarray;
1536
1537 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1538 {
1539         //unsigned int hashdepth = 0;
1540         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1541         r_hlsl_permutation_t *p;
1542         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1543         {
1544                 if (p->mode == mode && p->permutation == permutation)
1545                 {
1546                         //if (hashdepth > 10)
1547                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1548                         return p;
1549                 }
1550                 //hashdepth++;
1551         }
1552         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1553         p->mode = mode;
1554         p->permutation = permutation;
1555         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1556         r_hlsl_permutationhash[mode][hashindex] = p;
1557         //if (hashdepth > 10)
1558         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1559         return p;
1560 }
1561
1562 #include <d3dx9.h>
1563 //#include <d3dx9shader.h>
1564 //#include <d3dx9mesh.h>
1565
1566 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1567 {
1568         DWORD *vsbin = NULL;
1569         DWORD *psbin = NULL;
1570         fs_offset_t vsbinsize;
1571         fs_offset_t psbinsize;
1572 //      IDirect3DVertexShader9 *vs = NULL;
1573 //      IDirect3DPixelShader9 *ps = NULL;
1574         ID3DXBuffer *vslog = NULL;
1575         ID3DXBuffer *vsbuffer = NULL;
1576         ID3DXConstantTable *vsconstanttable = NULL;
1577         ID3DXBuffer *pslog = NULL;
1578         ID3DXBuffer *psbuffer = NULL;
1579         ID3DXConstantTable *psconstanttable = NULL;
1580         int vsresult = 0;
1581         int psresult = 0;
1582         char temp[MAX_INPUTLINE];
1583         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1584         char vabuf[1024];
1585         qboolean debugshader = gl_paranoid.integer != 0;
1586         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1587         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1588         if (!debugshader)
1589         {
1590                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1591                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1592         }
1593         if ((!vsbin && vertstring) || (!psbin && fragstring))
1594         {
1595                 const char* dllnames_d3dx9 [] =
1596                 {
1597                         "d3dx9_43.dll",
1598                         "d3dx9_42.dll",
1599                         "d3dx9_41.dll",
1600                         "d3dx9_40.dll",
1601                         "d3dx9_39.dll",
1602                         "d3dx9_38.dll",
1603                         "d3dx9_37.dll",
1604                         "d3dx9_36.dll",
1605                         "d3dx9_35.dll",
1606                         "d3dx9_34.dll",
1607                         "d3dx9_33.dll",
1608                         "d3dx9_32.dll",
1609                         "d3dx9_31.dll",
1610                         "d3dx9_30.dll",
1611                         "d3dx9_29.dll",
1612                         "d3dx9_28.dll",
1613                         "d3dx9_27.dll",
1614                         "d3dx9_26.dll",
1615                         "d3dx9_25.dll",
1616                         "d3dx9_24.dll",
1617                         NULL
1618                 };
1619                 dllhandle_t d3dx9_dll = NULL;
1620                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1621                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1622                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623                 dllfunction_t d3dx9_dllfuncs[] =
1624                 {
1625                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1626                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1627                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1628                         {NULL, NULL}
1629                 };
1630                 // 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...
1631 #ifndef ID3DXBuffer_GetBufferPointer
1632 #if !defined(__cplusplus) || defined(CINTERFACE)
1633 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1634 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1635 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1636 #else
1637 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1638 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1639 #define ID3DXBuffer_Release(p)            (p)->Release()
1640 #endif
1641 #endif
1642                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1643                 {
1644                         DWORD shaderflags = 0;
1645                         if (debugshader)
1646                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1647                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1648                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1649                         if (vertstring && vertstring[0])
1650                         {
1651                                 if (debugshader)
1652                                 {
1653                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1654                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1655                                 }
1656                                 else
1657                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1658                                 if (vsbuffer)
1659                                 {
1660                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1661                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1662                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1663                                         ID3DXBuffer_Release(vsbuffer);
1664                                 }
1665                                 if (vslog)
1666                                 {
1667                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1668                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1669                                         ID3DXBuffer_Release(vslog);
1670                                 }
1671                         }
1672                         if (fragstring && fragstring[0])
1673                         {
1674                                 if (debugshader)
1675                                 {
1676                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1677                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1678                                 }
1679                                 else
1680                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1681                                 if (psbuffer)
1682                                 {
1683                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1684                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1685                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1686                                         ID3DXBuffer_Release(psbuffer);
1687                                 }
1688                                 if (pslog)
1689                                 {
1690                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1691                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1692                                         ID3DXBuffer_Release(pslog);
1693                                 }
1694                         }
1695                         Sys_UnloadLibrary(&d3dx9_dll);
1696                 }
1697                 else
1698                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1699         }
1700         if (vsbin && psbin)
1701         {
1702                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1703                 if (FAILED(vsresult))
1704                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1705                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1706                 if (FAILED(psresult))
1707                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1708         }
1709         // free the shader data
1710         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1711         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1712 }
1713
1714 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1715 {
1716         int i;
1717         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1718         int vertstring_length = 0;
1719         int geomstring_length = 0;
1720         int fragstring_length = 0;
1721         char *t;
1722         char *sourcestring;
1723         char *vertstring, *geomstring, *fragstring;
1724         char permutationname[256];
1725         char cachename[256];
1726         int vertstrings_count = 0;
1727         int geomstrings_count = 0;
1728         int fragstrings_count = 0;
1729         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1730         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1731         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1732
1733         if (p->compiled)
1734                 return;
1735         p->compiled = true;
1736         p->vertexshader = NULL;
1737         p->pixelshader = NULL;
1738
1739         permutationname[0] = 0;
1740         cachename[0] = 0;
1741         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1742
1743         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1744         strlcat(cachename, "hlsl/", sizeof(cachename));
1745
1746         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1747         vertstrings_count = 0;
1748         geomstrings_count = 0;
1749         fragstrings_count = 0;
1750         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1751         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1752         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1753
1754         // the first pretext is which type of shader to compile as
1755         // (later these will all be bound together as a program object)
1756         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1757         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1758         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1759
1760         // the second pretext is the mode (for example a light source)
1761         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1762         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1763         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1764         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1765         strlcat(cachename, modeinfo->name, sizeof(cachename));
1766
1767         // now add all the permutation pretexts
1768         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769         {
1770                 if (permutation & (1ll<<i))
1771                 {
1772                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1773                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1774                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1775                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1776                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1777                 }
1778                 else
1779                 {
1780                         // keep line numbers correct
1781                         vertstrings_list[vertstrings_count++] = "\n";
1782                         geomstrings_list[geomstrings_count++] = "\n";
1783                         fragstrings_list[fragstrings_count++] = "\n";
1784                 }
1785         }
1786
1787         // add static parms
1788         R_CompileShader_AddStaticParms(mode, permutation);
1789         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1790         vertstrings_count += shaderstaticparms_count;
1791         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792         geomstrings_count += shaderstaticparms_count;
1793         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         fragstrings_count += shaderstaticparms_count;
1795
1796         // replace spaces in the cachename with _ characters
1797         for (i = 0;cachename[i];i++)
1798                 if (cachename[i] == ' ')
1799                         cachename[i] = '_';
1800
1801         // now append the shader text itself
1802         vertstrings_list[vertstrings_count++] = sourcestring;
1803         geomstrings_list[geomstrings_count++] = sourcestring;
1804         fragstrings_list[fragstrings_count++] = sourcestring;
1805
1806         vertstring_length = 0;
1807         for (i = 0;i < vertstrings_count;i++)
1808                 vertstring_length += (int)strlen(vertstrings_list[i]);
1809         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1810         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1811                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1812
1813         geomstring_length = 0;
1814         for (i = 0;i < geomstrings_count;i++)
1815                 geomstring_length += (int)strlen(geomstrings_list[i]);
1816         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1817         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1818                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1819
1820         fragstring_length = 0;
1821         for (i = 0;i < fragstrings_count;i++)
1822                 fragstring_length += (int)strlen(fragstrings_list[i]);
1823         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1824         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1825                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1826
1827         // try to load the cached shader, or generate one
1828         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1829
1830         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1831                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1832         else
1833                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1834
1835         // free the strings
1836         if (vertstring)
1837                 Mem_Free(vertstring);
1838         if (geomstring)
1839                 Mem_Free(geomstring);
1840         if (fragstring)
1841                 Mem_Free(fragstring);
1842         if (sourcestring)
1843                 Mem_Free(sourcestring);
1844 }
1845
1846 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1847 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1848 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);}
1849 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);}
1850 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);}
1851 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);}
1852
1853 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1854 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1855 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);}
1856 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);}
1857 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);}
1858 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);}
1859
1860 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1861 {
1862         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1863         if (r_hlsl_permutation != perm)
1864         {
1865                 r_hlsl_permutation = perm;
1866                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1867                 {
1868                         if (!r_hlsl_permutation->compiled)
1869                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1870                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1871                         {
1872                                 // remove features until we find a valid permutation
1873                                 int i;
1874                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875                                 {
1876                                         // reduce i more quickly whenever it would not remove any bits
1877                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1878                                         if (!(permutation & j))
1879                                                 continue;
1880                                         permutation -= j;
1881                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1882                                         if (!r_hlsl_permutation->compiled)
1883                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1884                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1885                                                 break;
1886                                 }
1887                                 if (i >= SHADERPERMUTATION_COUNT)
1888                                 {
1889                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1890                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891                                         return; // no bit left to clear, entire mode is broken
1892                                 }
1893                         }
1894                 }
1895                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1896                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1897         }
1898         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1899         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1900         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1901 }
1902 #endif
1903
1904 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1905 {
1906         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1907         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1908         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1909         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1910 }
1911
1912 void R_GLSL_Restart_f(void)
1913 {
1914         unsigned int i, limit;
1915         switch(vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 {
1920                         r_hlsl_permutation_t *p;
1921                         r_hlsl_permutation = NULL;
1922                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1923                         for (i = 0;i < limit;i++)
1924                         {
1925                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1926                                 {
1927                                         if (p->vertexshader)
1928                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1929                                         if (p->pixelshader)
1930                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1931                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1932                                 }
1933                         }
1934                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1935                 }
1936 #endif
1937                 break;
1938         case RENDERPATH_D3D10:
1939                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1940                 break;
1941         case RENDERPATH_D3D11:
1942                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943                 break;
1944         case RENDERPATH_GL20:
1945         case RENDERPATH_GLES2:
1946                 {
1947                         r_glsl_permutation_t *p;
1948                         r_glsl_permutation = NULL;
1949                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1950                         for (i = 0;i < limit;i++)
1951                         {
1952                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1953                                 {
1954                                         GL_Backend_FreeProgram(p->program);
1955                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1956                                 }
1957                         }
1958                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1959                 }
1960                 break;
1961         case RENDERPATH_GL11:
1962         case RENDERPATH_GL13:
1963         case RENDERPATH_GLES1:
1964                 break;
1965         case RENDERPATH_SOFT:
1966                 break;
1967         }
1968 }
1969
1970 static void R_GLSL_DumpShader_f(void)
1971 {
1972         int i, language, mode, dupe;
1973         char *text;
1974         shadermodeinfo_t *modeinfo;
1975         qfile_t *file;
1976
1977         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1978         {
1979                 modeinfo = shadermodeinfo[language];
1980                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1981                 {
1982                         // don't dump the same file multiple times (most or all shaders come from the same file)
1983                         for (dupe = mode - 1;dupe >= 0;dupe--)
1984                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1985                                         break;
1986                         if (dupe >= 0)
1987                                 continue;
1988                         text = modeinfo[mode].builtinstring;
1989                         if (!text)
1990                                 continue;
1991                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1992                         if (file)
1993                         {
1994                                 FS_Print(file, "/* The engine may define the following macros:\n");
1995                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1996                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1997                                         FS_Print(file, modeinfo[i].pretext);
1998                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1999                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2000                                 FS_Print(file, "*/\n");
2001                                 FS_Print(file, text);
2002                                 FS_Close(file);
2003                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2004                         }
2005                         else
2006                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2007                 }
2008         }
2009 }
2010
2011 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2012 {
2013         dpuint64 permutation = 0;
2014         if (r_trippy.integer && !notrippy)
2015                 permutation |= SHADERPERMUTATION_TRIPPY;
2016         permutation |= SHADERPERMUTATION_VIEWTINT;
2017         if (first)
2018                 permutation |= SHADERPERMUTATION_DIFFUSE;
2019         if (second)
2020                 permutation |= SHADERPERMUTATION_SPECULAR;
2021         if (texturemode == GL_MODULATE)
2022                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2023         else if (texturemode == GL_ADD)
2024                 permutation |= SHADERPERMUTATION_GLOW;
2025         else if (texturemode == GL_DECAL)
2026                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2027         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2028                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2029         if (suppresstexalpha)
2030                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2031         if (!second)
2032                 texturemode = GL_MODULATE;
2033         if (vid.allowalphatocoverage)
2034                 GL_AlphaToCoverage(false);
2035         switch (vid.renderpath)
2036         {
2037         case RENDERPATH_D3D9:
2038 #ifdef SUPPORTD3D
2039                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2040                 R_Mesh_TexBind(GL20TU_FIRST , first );
2041                 R_Mesh_TexBind(GL20TU_SECOND, second);
2042                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2043                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2044 #endif
2045                 break;
2046         case RENDERPATH_D3D10:
2047                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_D3D11:
2050                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_GL20:
2053         case RENDERPATH_GLES2:
2054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2055                 if (r_glsl_permutation->tex_Texture_First >= 0)
2056                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2057                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2058                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2059                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2061                 break;
2062         case RENDERPATH_GL13:
2063         case RENDERPATH_GLES1:
2064                 R_Mesh_TexBind(0, first );
2065                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2066                 R_Mesh_TexMatrix(0, NULL);
2067                 R_Mesh_TexBind(1, second);
2068                 if (second)
2069                 {
2070                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2071                         R_Mesh_TexMatrix(1, NULL);
2072                 }
2073                 break;
2074         case RENDERPATH_GL11:
2075                 R_Mesh_TexBind(0, first );
2076                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2077                 R_Mesh_TexMatrix(0, NULL);
2078                 break;
2079         case RENDERPATH_SOFT:
2080                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2081                 R_Mesh_TexBind(GL20TU_FIRST , first );
2082                 R_Mesh_TexBind(GL20TU_SECOND, second);
2083                 break;
2084         }
2085 }
2086
2087 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2088 {
2089         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2090 }
2091
2092 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2093 {
2094         dpuint64 permutation = 0;
2095         if (r_trippy.integer && !notrippy)
2096                 permutation |= SHADERPERMUTATION_TRIPPY;
2097         if (depthrgb)
2098                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2099         if (skeletal)
2100                 permutation |= SHADERPERMUTATION_SKELETAL;
2101
2102         if (vid.allowalphatocoverage)
2103                 GL_AlphaToCoverage(false);
2104         switch (vid.renderpath)
2105         {
2106         case RENDERPATH_D3D9:
2107 #ifdef SUPPORTD3D
2108                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2109 #endif
2110                 break;
2111         case RENDERPATH_D3D10:
2112                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2113                 break;
2114         case RENDERPATH_D3D11:
2115                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2116                 break;
2117         case RENDERPATH_GL20:
2118         case RENDERPATH_GLES2:
2119                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2121                 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);
2122 #endif
2123                 break;
2124         case RENDERPATH_GL13:
2125         case RENDERPATH_GLES1:
2126                 R_Mesh_TexBind(0, 0);
2127                 R_Mesh_TexBind(1, 0);
2128                 break;
2129         case RENDERPATH_GL11:
2130                 R_Mesh_TexBind(0, 0);
2131                 break;
2132         case RENDERPATH_SOFT:
2133                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2134                 break;
2135         }
2136 }
2137
2138 #define BLENDFUNC_ALLOWS_COLORMOD      1
2139 #define BLENDFUNC_ALLOWS_FOG           2
2140 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2141 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2142 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2143 static int R_BlendFuncFlags(int src, int dst)
2144 {
2145         int r = 0;
2146
2147         // a blendfunc allows colormod if:
2148         // a) it can never keep the destination pixel invariant, or
2149         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2150         // this is to prevent unintended side effects from colormod
2151
2152         // a blendfunc allows fog if:
2153         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2154         // this is to prevent unintended side effects from fog
2155
2156         // these checks are the output of fogeval.pl
2157
2158         r |= BLENDFUNC_ALLOWS_COLORMOD;
2159         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2160         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2161         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2162         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2163         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2167         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2168         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2169         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2170         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2172         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2173         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2179         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180
2181         return r;
2182 }
2183
2184 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)
2185 {
2186         // select a permutation of the lighting shader appropriate to this
2187         // combination of texture, entity, light source, and fogging, only use the
2188         // minimum features necessary to avoid wasting rendering time in the
2189         // fragment shader on features that are not being used
2190         dpuint64 permutation = 0;
2191         unsigned int mode = 0;
2192         int blendfuncflags;
2193         texture_t *t = rsurface.texture;
2194         float m16f[16];
2195         matrix4x4_t tempmatrix;
2196         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197         if (r_trippy.integer && !notrippy)
2198                 permutation |= SHADERPERMUTATION_TRIPPY;
2199         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2202                 permutation |= SHADERPERMUTATION_OCCLUDE;
2203         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2204                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2205         if (rsurfacepass == RSURFPASS_BACKGROUND)
2206         {
2207                 // distorted background
2208                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2209                 {
2210                         mode = SHADERMODE_WATER;
2211                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2212                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2213                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2214                         {
2215                                 // this is the right thing to do for wateralpha
2216                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2217                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2218                         }
2219                         else
2220                         {
2221                                 // this is the right thing to do for entity alpha
2222                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2223                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2224                         }
2225                 }
2226                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2227                 {
2228                         mode = SHADERMODE_REFRACTION;
2229                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2230                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2231                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2232                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2233                 }
2234                 else
2235                 {
2236                         mode = SHADERMODE_GENERIC;
2237                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2238                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                 }
2241                 if (vid.allowalphatocoverage)
2242                         GL_AlphaToCoverage(false);
2243         }
2244         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2245         {
2246                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2247                 {
2248                         switch(t->offsetmapping)
2249                         {
2250                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2251                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2253                         case OFFSETMAPPING_OFF: break;
2254                         }
2255                 }
2256                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2257                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2258                 // normalmap (deferred prepass), may use alpha test on diffuse
2259                 mode = SHADERMODE_DEFERREDGEOMETRY;
2260                 GL_BlendFunc(GL_ONE, GL_ZERO);
2261                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2262                 if (vid.allowalphatocoverage)
2263                         GL_AlphaToCoverage(false);
2264         }
2265         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2266         {
2267                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2268                 {
2269                         switch(t->offsetmapping)
2270                         {
2271                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2272                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2273                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2274                         case OFFSETMAPPING_OFF: break;
2275                         }
2276                 }
2277                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2280                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2281                 // light source
2282                 mode = SHADERMODE_LIGHTSOURCE;
2283                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2284                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2285                 if (VectorLength2(rtlightdiffuse) > 0)
2286                         permutation |= SHADERPERMUTATION_DIFFUSE;
2287                 if (VectorLength2(rtlightspecular) > 0)
2288                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2289                 if (r_refdef.fogenabled)
2290                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2291                 if (t->colormapping)
2292                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2293                 if (r_shadow_usingshadowmap2d)
2294                 {
2295                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2296                         if(r_shadow_shadowmapvsdct)
2297                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2298
2299                         if (r_shadow_shadowmap2ddepthbuffer)
2300                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2301                 }
2302                 if (t->reflectmasktexture)
2303                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2305                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2306                 if (vid.allowalphatocoverage)
2307                         GL_AlphaToCoverage(false);
2308         }
2309         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2310         {
2311                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2312                 {
2313                         switch(t->offsetmapping)
2314                         {
2315                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2316                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318                         case OFFSETMAPPING_OFF: break;
2319                         }
2320                 }
2321                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2324                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2325                 // directional model lighting
2326                 mode = SHADERMODE_LIGHTDIRECTION;
2327                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2328                         permutation |= SHADERPERMUTATION_GLOW;
2329                 if (VectorLength2(t->render_modellight_diffuse))
2330                         permutation |= SHADERPERMUTATION_DIFFUSE;
2331                 if (VectorLength2(t->render_modellight_specular) > 0)
2332                         permutation |= SHADERPERMUTATION_SPECULAR;
2333                 if (r_refdef.fogenabled)
2334                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2335                 if (t->colormapping)
2336                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2337                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2338                 {
2339                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2340                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2341
2342                         if (r_shadow_shadowmap2ddepthbuffer)
2343                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2344                 }
2345                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346                         permutation |= SHADERPERMUTATION_REFLECTION;
2347                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2348                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2349                 if (t->reflectmasktexture)
2350                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2351                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2352                 {
2353                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2354                         if (r_shadow_bouncegrid_state.directional)
2355                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2356                 }
2357                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2358                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2359                 // when using alphatocoverage, we don't need alphakill
2360                 if (vid.allowalphatocoverage)
2361                 {
2362                         if (r_transparent_alphatocoverage.integer)
2363                         {
2364                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2365                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2366                         }
2367                         else
2368                                 GL_AlphaToCoverage(false);
2369                 }
2370         }
2371         else
2372         {
2373                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2374                 {
2375                         switch(t->offsetmapping)
2376                         {
2377                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2378                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2380                         case OFFSETMAPPING_OFF: break;
2381                         }
2382                 }
2383                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2384                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2385                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2386                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2387                 // lightmapped wall
2388                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2389                         permutation |= SHADERPERMUTATION_GLOW;
2390                 if (r_refdef.fogenabled)
2391                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2392                 if (t->colormapping)
2393                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2394                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2395                 {
2396                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2397                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2398
2399                         if (r_shadow_shadowmap2ddepthbuffer)
2400                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2401                 }
2402                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403                         permutation |= SHADERPERMUTATION_REFLECTION;
2404                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2405                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406                 if (t->reflectmasktexture)
2407                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408                 if (FAKELIGHT_ENABLED)
2409                 {
2410                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2411                         mode = SHADERMODE_FAKELIGHT;
2412                         permutation |= SHADERPERMUTATION_DIFFUSE;
2413                         if (VectorLength2(t->render_lightmap_specular) > 0)
2414                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2415                 }
2416                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2417                 {
2418                         // deluxemapping (light direction texture)
2419                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2420                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2421                         else
2422                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2423                         permutation |= SHADERPERMUTATION_DIFFUSE;
2424                         if (VectorLength2(t->render_lightmap_specular) > 0)
2425                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2426                 }
2427                 else if (r_glsl_deluxemapping.integer >= 2)
2428                 {
2429                         // fake deluxemapping (uniform light direction in tangentspace)
2430                         if (rsurface.uselightmaptexture)
2431                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2432                         else
2433                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2434                         permutation |= SHADERPERMUTATION_DIFFUSE;
2435                         if (VectorLength2(t->render_lightmap_specular) > 0)
2436                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2437                 }
2438                 else if (rsurface.uselightmaptexture)
2439                 {
2440                         // ordinary lightmapping (q1bsp, q3bsp)
2441                         mode = SHADERMODE_LIGHTMAP;
2442                 }
2443                 else
2444                 {
2445                         // ordinary vertex coloring (q3bsp)
2446                         mode = SHADERMODE_VERTEXCOLOR;
2447                 }
2448                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2449                 {
2450                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2451                         if (r_shadow_bouncegrid_state.directional)
2452                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2453                 }
2454                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2455                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2456                 // when using alphatocoverage, we don't need alphakill
2457                 if (vid.allowalphatocoverage)
2458                 {
2459                         if (r_transparent_alphatocoverage.integer)
2460                         {
2461                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2462                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2463                         }
2464                         else
2465                                 GL_AlphaToCoverage(false);
2466                 }
2467         }
2468         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2469                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2470         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2471                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2472         switch(vid.renderpath)
2473         {
2474         case RENDERPATH_D3D9:
2475 #ifdef SUPPORTD3D
2476                 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);
2477                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2478                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2479                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2480                 if (mode == SHADERMODE_LIGHTSOURCE)
2481                 {
2482                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2483                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2484                 }
2485                 else
2486                 {
2487                         if (mode == SHADERMODE_LIGHTDIRECTION)
2488                         {
2489                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2490                         }
2491                 }
2492                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2493                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2494                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2495                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2496                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2497
2498                 if (mode == SHADERMODE_LIGHTSOURCE)
2499                 {
2500                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2501                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2502                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2503                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2504                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2505
2506                         // additive passes are only darkened by fog, not tinted
2507                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2508                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2509                 }
2510                 else
2511                 {
2512                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2513                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2514                         if (mode == SHADERMODE_FLATCOLOR)
2515                         {
2516                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2517                         }
2518                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2519                         {
2520                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2521                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2522                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2523                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2524                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2525                         }
2526                         else
2527                         {
2528                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2529                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2530                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2531                         }
2532                         // additive passes are only darkened by fog, not tinted
2533                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2534                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2535                         else
2536                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2537                         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);
2538                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2539                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2540                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2541                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2542                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2543                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2544                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2545                         if (mode == SHADERMODE_WATER)
2546                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2547                 }
2548                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2549                 {
2550                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2551                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2552                 }
2553                 else
2554                 {
2555                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2556                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2557                 }
2558                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2559                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2560                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2561                 if (t->pantstexture)
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2563                 else
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2565                 if (t->shirttexture)
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2567                 else
2568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2569                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2570                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2571                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2572                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2573                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2574                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2575                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2576                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2577                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2578                         );
2579                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2580                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2581                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2582                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2583
2584                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2585                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2586                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2587                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2588                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2589                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2590                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2591                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2592                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2593                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2594                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2595                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2596                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2597                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2598                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2599                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2600                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2601                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2602                 {
2603                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2604                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2605                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2606                 }
2607                 else
2608                 {
2609                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2610                 }
2611 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2612                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2613                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2614                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2615                 {
2616                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2617                         if (rsurface.rtlight)
2618                         {
2619                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2620                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2621                         }
2622                 }
2623 #endif
2624                 break;
2625         case RENDERPATH_D3D10:
2626                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2627                 break;
2628         case RENDERPATH_D3D11:
2629                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2630                 break;
2631         case RENDERPATH_GL20:
2632         case RENDERPATH_GLES2:
2633                 if (!vid.useinterleavedarrays)
2634                 {
2635                         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);
2636                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2637                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2638                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2639                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2640                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2641                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2642                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2643                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2644                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2645                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2646                 }
2647                 else
2648                 {
2649                         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);
2650                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2651                 }
2652                 // this has to be after RSurf_PrepareVerticesForBatch
2653                 if (rsurface.batchskeletaltransform3x4buffer)
2654                         permutation |= SHADERPERMUTATION_SKELETAL;
2655                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2656 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2657                 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);
2658 #endif
2659                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2660                 if (mode == SHADERMODE_LIGHTSOURCE)
2661                 {
2662                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2663                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2664                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2665                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2666                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2667                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2668         
2669                         // additive passes are only darkened by fog, not tinted
2670                         if (r_glsl_permutation->loc_FogColor >= 0)
2671                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2672                         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);
2673                 }
2674                 else
2675                 {
2676                         if (mode == SHADERMODE_FLATCOLOR)
2677                         {
2678                                 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]);
2679                         }
2680                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2681                         {
2682                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2683                                 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]);
2684                                 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]);
2685                                 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]);
2686                                 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]);
2687                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2688                                 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]);
2689                         }
2690                         else
2691                         {
2692                                 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]);
2693                                 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]);
2694                                 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]);
2695                                 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]);
2696                                 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]);
2697                         }
2698                         // additive passes are only darkened by fog, not tinted
2699                         if (r_glsl_permutation->loc_FogColor >= 0)
2700                         {
2701                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2702                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2703                                 else
2704                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2705                         }
2706                         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);
2707                         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]);
2708                         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]);
2709                         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);
2710                         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);
2711                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2712                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2713                         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);
2714                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2715                 }
2716                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2717                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2718                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2719                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2720                 {
2721                         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]);
2722                         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]);
2723                 }
2724                 else
2725                 {
2726                         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]);
2727                         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]);
2728                 }
2729
2730                 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]);
2731                 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));
2732                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2733                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2734                 {
2735                         if (t->pantstexture)
2736                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2737                         else
2738                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2739                 }
2740                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2741                 {
2742                         if (t->shirttexture)
2743                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2744                         else
2745                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2746                 }
2747                 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]);
2748                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2749                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2750                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2751                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2752                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2753                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2754                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2755                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2756                         );
2757                 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);
2758                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2759                 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]);
2760                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2761                 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);}
2762                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2763
2764                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2765                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2766                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2767                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2768                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2769                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2770                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2771                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2772                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2773                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2774                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2775                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2776                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2777                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2778                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2779                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2780                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2781                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2782                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2783                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2784                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2785                 {
2786                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2787                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2788                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2789                 }
2790                 else
2791                 {
2792                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2793                 }
2794                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2795                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2796                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2797                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2798                 {
2799                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2800                         if (rsurface.rtlight)
2801                         {
2802                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2803                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2804                         }
2805                 }
2806                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2807                 CHECKGLERROR
2808                 break;
2809         case RENDERPATH_GL11:
2810         case RENDERPATH_GL13:
2811         case RENDERPATH_GLES1:
2812                 break;
2813         case RENDERPATH_SOFT:
2814                 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);
2815                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2816                 R_SetupShader_SetPermutationSoft(mode, permutation);
2817                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2818                 if (mode == SHADERMODE_LIGHTSOURCE)
2819                 {
2820                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2821                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2822                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2823                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2824                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2825                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2826         
2827                         // additive passes are only darkened by fog, not tinted
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2829                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2830                 }
2831                 else
2832                 {
2833                         if (mode == SHADERMODE_FLATCOLOR)
2834                         {
2835                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2836                         }
2837                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2838                         {
2839                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2840                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2841                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2842                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2844                         }
2845                         else
2846                         {
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2850                         }
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2853                         // additive passes are only darkened by fog, not tinted
2854                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2856                         else
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2858                         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);
2859                         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]);
2860                         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]);
2861                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2862                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2863                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2866                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2867                 }
2868                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2869                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2870                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2871                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2872                 {
2873                         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]);
2874                         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]);
2875                 }
2876                 else
2877                 {
2878                         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]);
2879                         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]);
2880                 }
2881
2882                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2883                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2884                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2885                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2886                 {
2887                         if (t->pantstexture)
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2889                         else
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2891                 }
2892                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2893                 {
2894                         if (t->shirttexture)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2898                 }
2899                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2904                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2905                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2907                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2908                         );
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2910                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2911                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2912                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2913
2914                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2915                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2916                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2917                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2919                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2920                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2921                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2922                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2923                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2924                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2925                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2926                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2927                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2928                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2929                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2930                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2931                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2932                 {
2933                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2934                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2935                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2936                 }
2937                 else
2938                 {
2939                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2940                 }
2941 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2942                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2943                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2944                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2945                 {
2946                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2947                         if (rsurface.rtlight)
2948                         {
2949                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2950                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2951                         }
2952                 }
2953                 break;
2954         }
2955 }
2956
2957 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2958 {
2959         // select a permutation of the lighting shader appropriate to this
2960         // combination of texture, entity, light source, and fogging, only use the
2961         // minimum features necessary to avoid wasting rendering time in the
2962         // fragment shader on features that are not being used
2963         dpuint64 permutation = 0;
2964         unsigned int mode = 0;
2965         const float *lightcolorbase = rtlight->currentcolor;
2966         float ambientscale = rtlight->ambientscale;
2967         float diffusescale = rtlight->diffusescale;
2968         float specularscale = rtlight->specularscale;
2969         // this is the location of the light in view space
2970         vec3_t viewlightorigin;
2971         // this transforms from view space (camera) to light space (cubemap)
2972         matrix4x4_t viewtolight;
2973         matrix4x4_t lighttoview;
2974         float viewtolight16f[16];
2975         // light source
2976         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2977         if (rtlight->currentcubemap != r_texture_whitecube)
2978                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2979         if (diffusescale > 0)
2980                 permutation |= SHADERPERMUTATION_DIFFUSE;
2981         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2982                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2983         if (r_shadow_usingshadowmap2d)
2984         {
2985                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2986                 if (r_shadow_shadowmapvsdct)
2987                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2988
2989                 if (r_shadow_shadowmap2ddepthbuffer)
2990                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2991         }
2992         if (vid.allowalphatocoverage)
2993                 GL_AlphaToCoverage(false);
2994         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2995         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2996         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2997         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2998         switch(vid.renderpath)
2999         {
3000         case RENDERPATH_D3D9:
3001 #ifdef SUPPORTD3D
3002                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3003                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3004                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3005                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3006                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3007                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3008                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3009                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3010                 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);
3011                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3012                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3013
3014                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3015                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3016                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3017                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3018                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3019 #endif
3020                 break;
3021         case RENDERPATH_D3D10:
3022                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3023                 break;
3024         case RENDERPATH_D3D11:
3025                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3026                 break;
3027         case RENDERPATH_GL20:
3028         case RENDERPATH_GLES2:
3029                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3030                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3031                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3032                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3033                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3034                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3035                 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]);
3036                 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]);
3037                 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);
3038                 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]);
3039                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3040
3041                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3042                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3043                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3044                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3045                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3046                 break;
3047         case RENDERPATH_GL11:
3048         case RENDERPATH_GL13:
3049         case RENDERPATH_GLES1:
3050                 break;
3051         case RENDERPATH_SOFT:
3052                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3053                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3054                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3055                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3056                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3057                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3058                 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]);
3059                 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]);
3060                 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);
3061                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3062                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3063
3064                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3065                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3066                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3067                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3068                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3069                 break;
3070         }
3071 }
3072
3073 #define SKINFRAME_HASH 1024
3074
3075 typedef struct
3076 {
3077         unsigned int loadsequence; // incremented each level change
3078         memexpandablearray_t array;
3079         skinframe_t *hash[SKINFRAME_HASH];
3080 }
3081 r_skinframe_t;
3082 r_skinframe_t r_skinframe;
3083
3084 void R_SkinFrame_PrepareForPurge(void)
3085 {
3086         r_skinframe.loadsequence++;
3087         // wrap it without hitting zero
3088         if (r_skinframe.loadsequence >= 200)
3089                 r_skinframe.loadsequence = 1;
3090 }
3091
3092 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3093 {
3094         if (!skinframe)
3095                 return;
3096         // mark the skinframe as used for the purging code
3097         skinframe->loadsequence = r_skinframe.loadsequence;
3098 }
3099
3100 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3101 {
3102         if (s->merged == s->base)
3103                 s->merged = NULL;
3104         R_PurgeTexture(s->stain); s->stain = NULL;
3105         R_PurgeTexture(s->merged); s->merged = NULL;
3106         R_PurgeTexture(s->base); s->base = NULL;
3107         R_PurgeTexture(s->pants); s->pants = NULL;
3108         R_PurgeTexture(s->shirt); s->shirt = NULL;
3109         R_PurgeTexture(s->nmap); s->nmap = NULL;
3110         R_PurgeTexture(s->gloss); s->gloss = NULL;
3111         R_PurgeTexture(s->glow); s->glow = NULL;
3112         R_PurgeTexture(s->fog); s->fog = NULL;
3113         R_PurgeTexture(s->reflect); s->reflect = NULL;
3114         s->loadsequence = 0;
3115 }
3116
3117 void R_SkinFrame_Purge(void)
3118 {
3119         int i;
3120         skinframe_t *s;
3121         for (i = 0;i < SKINFRAME_HASH;i++)
3122         {
3123                 for (s = r_skinframe.hash[i];s;s = s->next)
3124                 {
3125                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3126                                 R_SkinFrame_PurgeSkinFrame(s);
3127                 }
3128         }
3129 }
3130
3131 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3132         skinframe_t *item;
3133         char basename[MAX_QPATH];
3134
3135         Image_StripImageExtension(name, basename, sizeof(basename));
3136
3137         if( last == NULL ) {
3138                 int hashindex;
3139                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3140                 item = r_skinframe.hash[hashindex];
3141         } else {
3142                 item = last->next;
3143         }
3144
3145         // linearly search through the hash bucket
3146         for( ; item ; item = item->next ) {
3147                 if( !strcmp( item->basename, basename ) ) {
3148                         return item;
3149                 }
3150         }
3151         return NULL;
3152 }
3153
3154 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3155 {
3156         skinframe_t *item;
3157         int hashindex;
3158         char basename[MAX_QPATH];
3159
3160         Image_StripImageExtension(name, basename, sizeof(basename));
3161
3162         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3163         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3164                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3165                         break;
3166
3167         if (!item)
3168         {
3169                 if (!add)
3170                         return NULL;
3171                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3172                 memset(item, 0, sizeof(*item));
3173                 strlcpy(item->basename, basename, sizeof(item->basename));
3174                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3175                 item->comparewidth = comparewidth;
3176                 item->compareheight = compareheight;
3177                 item->comparecrc = comparecrc;
3178                 item->next = r_skinframe.hash[hashindex];
3179                 r_skinframe.hash[hashindex] = item;
3180         }
3181         else if (textureflags & TEXF_FORCE_RELOAD)
3182         {
3183                 if (!add)
3184                         return NULL;
3185                 R_SkinFrame_PurgeSkinFrame(item);
3186         }
3187
3188         R_SkinFrame_MarkUsed(item);
3189         return item;
3190 }
3191
3192 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3193         { \
3194                 unsigned long long avgcolor[5], wsum; \
3195                 int pix, comp, w; \
3196                 avgcolor[0] = 0; \
3197                 avgcolor[1] = 0; \
3198                 avgcolor[2] = 0; \
3199                 avgcolor[3] = 0; \
3200                 avgcolor[4] = 0; \
3201                 wsum = 0; \
3202                 for(pix = 0; pix < cnt; ++pix) \
3203                 { \
3204                         w = 0; \
3205                         for(comp = 0; comp < 3; ++comp) \
3206                                 w += getpixel; \
3207                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3208                         { \
3209                                 ++wsum; \
3210                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3211                                 w = getpixel; \
3212                                 for(comp = 0; comp < 3; ++comp) \
3213                                         avgcolor[comp] += getpixel * w; \
3214                                 avgcolor[3] += w; \
3215                         } \
3216                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3217                         avgcolor[4] += getpixel; \
3218                 } \
3219                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3220                         avgcolor[3] = 1; \
3221                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3222                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3223                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3224                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3225         }
3226
3227 extern cvar_t gl_picmip;
3228 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3229 {
3230         int j;
3231         unsigned char *pixels;
3232         unsigned char *bumppixels;
3233         unsigned char *basepixels = NULL;
3234         int basepixels_width = 0;
3235         int basepixels_height = 0;
3236         skinframe_t *skinframe;
3237         rtexture_t *ddsbase = NULL;
3238         qboolean ddshasalpha = false;
3239         float ddsavgcolor[4];
3240         char basename[MAX_QPATH];
3241         int miplevel = R_PicmipForFlags(textureflags);
3242         int savemiplevel = miplevel;
3243         int mymiplevel;
3244         char vabuf[1024];
3245
3246         if (cls.state == ca_dedicated)
3247                 return NULL;
3248
3249         // return an existing skinframe if already loaded
3250         // if loading of the first image fails, don't make a new skinframe as it
3251         // would cause all future lookups of this to be missing
3252         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3253         if (skinframe && skinframe->base)
3254                 return skinframe;
3255
3256         Image_StripImageExtension(name, basename, sizeof(basename));
3257
3258         // check for DDS texture file first
3259         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3260         {
3261                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3262                 if (basepixels == NULL && fallbacknotexture)
3263                         basepixels = Image_GenerateNoTexture();
3264                 if (basepixels == NULL)
3265                         return NULL;
3266         }
3267
3268         // FIXME handle miplevel
3269
3270         if (developer_loading.integer)
3271                 Con_Printf("loading skin \"%s\"\n", name);
3272
3273         // we've got some pixels to store, so really allocate this new texture now
3274         if (!skinframe)
3275                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3276         textureflags &= ~TEXF_FORCE_RELOAD;
3277         skinframe->stain = NULL;
3278         skinframe->merged = NULL;
3279         skinframe->base = NULL;
3280         skinframe->pants = NULL;
3281         skinframe->shirt = NULL;
3282         skinframe->nmap = NULL;
3283         skinframe->gloss = NULL;
3284         skinframe->glow = NULL;
3285         skinframe->fog = NULL;
3286         skinframe->reflect = NULL;
3287         skinframe->hasalpha = false;
3288         // we could store the q2animname here too
3289
3290         if (ddsbase)
3291         {
3292                 skinframe->base = ddsbase;
3293                 skinframe->hasalpha = ddshasalpha;
3294                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3295                 if (r_loadfog && skinframe->hasalpha)
3296                         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);
3297                 //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]);
3298         }
3299         else
3300         {
3301                 basepixels_width = image_width;
3302                 basepixels_height = image_height;
3303                 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);
3304                 if (textureflags & TEXF_ALPHA)
3305                 {
3306                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3307                         {
3308                                 if (basepixels[j] < 255)
3309                                 {
3310                                         skinframe->hasalpha = true;
3311                                         break;
3312                                 }
3313                         }
3314                         if (r_loadfog && skinframe->hasalpha)
3315                         {
3316                                 // has transparent pixels
3317                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3318                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3319                                 {
3320                                         pixels[j+0] = 255;
3321                                         pixels[j+1] = 255;
3322                                         pixels[j+2] = 255;
3323                                         pixels[j+3] = basepixels[j+3];
3324                                 }
3325                                 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);
3326                                 Mem_Free(pixels);
3327                         }
3328                 }
3329                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3330 #ifndef USE_GLES2
3331                 //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]);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3333                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3334                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3335                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3336 #endif
3337         }
3338
3339         if (r_loaddds)
3340         {
3341                 mymiplevel = savemiplevel;
3342                 if (r_loadnormalmap)
3343                         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);
3344                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3345                 if (r_loadgloss)
3346                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3347                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3348                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3349                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3350         }
3351
3352         // _norm is the name used by tenebrae and has been adopted as standard
3353         if (r_loadnormalmap && skinframe->nmap == NULL)
3354         {
3355                 mymiplevel = savemiplevel;
3356                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3357                 {
3358                         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);
3359                         Mem_Free(pixels);
3360                         pixels = NULL;
3361                 }
3362                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3363                 {
3364                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3365                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3366                         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);
3367                         Mem_Free(pixels);
3368                         Mem_Free(bumppixels);
3369                 }
3370                 else if (r_shadow_bumpscale_basetexture.value > 0)
3371                 {
3372                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3373                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3374                         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);
3375                         Mem_Free(pixels);
3376                 }
3377 #ifndef USE_GLES2
3378                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3379                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3380 #endif
3381         }
3382
3383         // _luma is supported only for tenebrae compatibility
3384         // _glow is the preferred name
3385         mymiplevel = savemiplevel;
3386         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))))
3387         {
3388                 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);
3389 #ifndef USE_GLES2
3390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3391                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3392 #endif
3393                 Mem_Free(pixels);pixels = NULL;
3394         }
3395
3396         mymiplevel = savemiplevel;
3397         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3398         {
3399                 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);
3400 #ifndef USE_GLES2
3401                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3402                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3403 #endif
3404                 Mem_Free(pixels);
3405                 pixels = NULL;
3406         }
3407
3408         mymiplevel = savemiplevel;
3409         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3410         {
3411                 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);
3412 #ifndef USE_GLES2
3413                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3414                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3415 #endif
3416                 Mem_Free(pixels);
3417                 pixels = NULL;
3418         }
3419
3420         mymiplevel = savemiplevel;
3421         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3422         {
3423                 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);
3424 #ifndef USE_GLES2
3425                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3426                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3427 #endif
3428                 Mem_Free(pixels);
3429                 pixels = NULL;
3430         }
3431
3432         mymiplevel = savemiplevel;
3433         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3434         {
3435                 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);
3436 #ifndef USE_GLES2
3437                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3438                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3439 #endif
3440                 Mem_Free(pixels);
3441                 pixels = NULL;
3442         }
3443
3444         if (basepixels)
3445                 Mem_Free(basepixels);
3446
3447         return skinframe;
3448 }
3449
3450 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3451 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3452 {
3453         int i;
3454         skinframe_t *skinframe;
3455         char vabuf[1024];
3456
3457         if (cls.state == ca_dedicated)
3458                 return NULL;
3459
3460         // if already loaded just return it, otherwise make a new skinframe
3461         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3462         if (skinframe->base)
3463                 return skinframe;
3464         textureflags &= ~TEXF_FORCE_RELOAD;
3465
3466         skinframe->stain = NULL;
3467         skinframe->merged = NULL;
3468         skinframe->base = NULL;
3469         skinframe->pants = NULL;
3470         skinframe->shirt = NULL;
3471         skinframe->nmap = NULL;
3472         skinframe->gloss = NULL;
3473         skinframe->glow = NULL;
3474         skinframe->fog = NULL;
3475         skinframe->reflect = NULL;
3476         skinframe->hasalpha = false;
3477
3478         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3479         if (!skindata)
3480                 return NULL;
3481
3482         if (developer_loading.integer)
3483                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3484
3485         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3486         {
3487                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3488                 unsigned char *b = a + width * height * 4;
3489                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3490                 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);
3491                 Mem_Free(a);
3492         }
3493         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3494         if (textureflags & TEXF_ALPHA)
3495         {
3496                 for (i = 3;i < width * height * 4;i += 4)
3497                 {
3498                         if (skindata[i] < 255)
3499                         {
3500                                 skinframe->hasalpha = true;
3501                                 break;
3502                         }
3503                 }
3504                 if (r_loadfog && skinframe->hasalpha)
3505                 {
3506                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3507                         memcpy(fogpixels, skindata, width * height * 4);
3508                         for (i = 0;i < width * height * 4;i += 4)
3509                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3510                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3511                         Mem_Free(fogpixels);
3512                 }
3513         }
3514
3515         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3516         //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]);
3517
3518         return skinframe;
3519 }
3520
3521 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3522 {
3523         int i;
3524         int featuresmask;
3525         skinframe_t *skinframe;
3526
3527         if (cls.state == ca_dedicated)
3528                 return NULL;
3529
3530         // if already loaded just return it, otherwise make a new skinframe
3531         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3532         if (skinframe->base)
3533                 return skinframe;
3534         //textureflags &= ~TEXF_FORCE_RELOAD;
3535
3536         skinframe->stain = NULL;
3537         skinframe->merged = NULL;
3538         skinframe->base = NULL;
3539         skinframe->pants = NULL;
3540         skinframe->shirt = NULL;
3541         skinframe->nmap = NULL;
3542         skinframe->gloss = NULL;
3543         skinframe->glow = NULL;
3544         skinframe->fog = NULL;
3545         skinframe->reflect = NULL;
3546         skinframe->hasalpha = false;
3547
3548         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3549         if (!skindata)
3550                 return NULL;
3551
3552         if (developer_loading.integer)
3553                 Con_Printf("loading quake skin \"%s\"\n", name);
3554
3555         // 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)
3556         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3557         memcpy(skinframe->qpixels, skindata, width*height);
3558         skinframe->qwidth = width;
3559         skinframe->qheight = height;
3560
3561         featuresmask = 0;
3562         for (i = 0;i < width * height;i++)
3563                 featuresmask |= palette_featureflags[skindata[i]];
3564
3565         skinframe->hasalpha = false;
3566         // fence textures
3567         if (name[0] == '{')
3568                 skinframe->hasalpha = true;
3569         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3570         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3571         skinframe->qgeneratemerged = true;
3572         skinframe->qgeneratebase = skinframe->qhascolormapping;
3573         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3574
3575         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3576         //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]);
3577
3578         return skinframe;
3579 }
3580
3581 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3582 {
3583         int width;
3584         int height;
3585         unsigned char *skindata;
3586         char vabuf[1024];
3587
3588         if (!skinframe->qpixels)
3589                 return;
3590
3591         if (!skinframe->qhascolormapping)
3592                 colormapped = false;
3593
3594         if (colormapped)
3595         {
3596                 if (!skinframe->qgeneratebase)
3597                         return;
3598         }
3599         else
3600         {
3601                 if (!skinframe->qgeneratemerged)
3602                         return;
3603         }
3604
3605         width = skinframe->qwidth;
3606         height = skinframe->qheight;
3607         skindata = skinframe->qpixels;
3608
3609         if (skinframe->qgeneratenmap)
3610         {
3611                 unsigned char *a, *b;
3612                 skinframe->qgeneratenmap = false;
3613                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3614                 b = a + width * height * 4;
3615                 // use either a custom palette or the quake palette
3616                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3617                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3618                 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);
3619                 Mem_Free(a);
3620         }
3621
3622         if (skinframe->qgenerateglow)
3623         {
3624                 skinframe->qgenerateglow = false;
3625                 if (skinframe->hasalpha) // fence textures
3626                         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
3627                 else
3628                         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
3629         }
3630
3631         if (colormapped)
3632         {
3633                 skinframe->qgeneratebase = false;
3634                 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);
3635                 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);
3636                 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);
3637         }
3638         else
3639         {
3640                 skinframe->qgeneratemerged = false;
3641                 if (skinframe->hasalpha) // fence textures
3642                         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);
3643                 else
3644                         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);
3645         }
3646
3647         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3648         {
3649                 Mem_Free(skinframe->qpixels);
3650                 skinframe->qpixels = NULL;
3651         }
3652 }
3653
3654 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)
3655 {
3656         int i;
3657         skinframe_t *skinframe;
3658         char vabuf[1024];
3659
3660         if (cls.state == ca_dedicated)
3661                 return NULL;
3662
3663         // if already loaded just return it, otherwise make a new skinframe
3664         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3665         if (skinframe->base)
3666                 return skinframe;
3667         textureflags &= ~TEXF_FORCE_RELOAD;
3668
3669         skinframe->stain = NULL;
3670         skinframe->merged = NULL;
3671         skinframe->base = NULL;
3672         skinframe->pants = NULL;
3673         skinframe->shirt = NULL;
3674         skinframe->nmap = NULL;
3675         skinframe->gloss = NULL;
3676         skinframe->glow = NULL;
3677         skinframe->fog = NULL;
3678         skinframe->reflect = NULL;
3679         skinframe->hasalpha = false;
3680
3681         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3682         if (!skindata)
3683                 return NULL;
3684
3685         if (developer_loading.integer)
3686                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3687
3688         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3689         if ((textureflags & TEXF_ALPHA) && alphapalette)
3690         {
3691                 for (i = 0;i < width * height;i++)
3692                 {
3693                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3694                         {
3695                                 skinframe->hasalpha = true;
3696                                 break;
3697                         }
3698                 }
3699                 if (r_loadfog && skinframe->hasalpha)
3700                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3701         }
3702
3703         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3704         //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]);
3705
3706         return skinframe;
3707 }
3708
3709 skinframe_t *R_SkinFrame_LoadMissing(void)
3710 {
3711         skinframe_t *skinframe;
3712
3713         if (cls.state == ca_dedicated)
3714                 return NULL;
3715
3716         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3717         skinframe->stain = NULL;
3718         skinframe->merged = NULL;
3719         skinframe->base = NULL;
3720         skinframe->pants = NULL;
3721         skinframe->shirt = NULL;
3722         skinframe->nmap = NULL;
3723         skinframe->gloss = NULL;
3724         skinframe->glow = NULL;
3725         skinframe->fog = NULL;
3726         skinframe->reflect = NULL;
3727         skinframe->hasalpha = false;
3728
3729         skinframe->avgcolor[0] = rand() / RAND_MAX;
3730         skinframe->avgcolor[1] = rand() / RAND_MAX;
3731         skinframe->avgcolor[2] = rand() / RAND_MAX;
3732         skinframe->avgcolor[3] = 1;
3733
3734         return skinframe;
3735 }
3736
3737 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3738 {
3739         int x, y;
3740         static unsigned char pix[16][16][4];
3741
3742         if (cls.state == ca_dedicated)
3743                 return NULL;
3744
3745         // this makes a light grey/dark grey checkerboard texture
3746         if (!pix[0][0][3])
3747         {
3748                 for (y = 0; y < 16; y++)
3749                 {
3750                         for (x = 0; x < 16; x++)
3751                         {
3752                                 if ((y < 8) ^ (x < 8))
3753                                 {
3754                                         pix[y][x][0] = 128;
3755                                         pix[y][x][1] = 128;
3756                                         pix[y][x][2] = 128;
3757                                         pix[y][x][3] = 255;
3758                                 }
3759                                 else
3760                                 {
3761                                         pix[y][x][0] = 64;
3762                                         pix[y][x][1] = 64;
3763                                         pix[y][x][2] = 64;
3764                                         pix[y][x][3] = 255;
3765                                 }
3766                         }
3767                 }
3768         }
3769
3770         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3771 }
3772
3773 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3774 {
3775         skinframe_t *skinframe;
3776         if (cls.state == ca_dedicated)
3777                 return NULL;
3778         // if already loaded just return it, otherwise make a new skinframe
3779         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3780         if (skinframe->base)
3781                 return skinframe;
3782         textureflags &= ~TEXF_FORCE_RELOAD;
3783         skinframe->stain = NULL;
3784         skinframe->merged = NULL;
3785         skinframe->base = NULL;
3786         skinframe->pants = NULL;
3787         skinframe->shirt = NULL;
3788         skinframe->nmap = NULL;
3789         skinframe->gloss = NULL;
3790         skinframe->glow = NULL;
3791         skinframe->fog = NULL;
3792         skinframe->reflect = NULL;
3793         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3794         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3795         if (!tex)
3796                 return NULL;
3797         if (developer_loading.integer)
3798                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3799         skinframe->base = skinframe->merged = tex;
3800         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3801         return skinframe;
3802 }
3803
3804 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3805 typedef struct suffixinfo_s
3806 {
3807         const char *suffix;
3808         qboolean flipx, flipy, flipdiagonal;
3809 }
3810 suffixinfo_t;
3811 static suffixinfo_t suffix[3][6] =
3812 {
3813         {
3814                 {"px",   false, false, false},
3815                 {"nx",   false, false, false},
3816                 {"py",   false, false, false},
3817                 {"ny",   false, false, false},
3818                 {"pz",   false, false, false},
3819                 {"nz",   false, false, false}
3820         },
3821         {
3822                 {"posx", false, false, false},
3823                 {"negx", false, false, false},
3824                 {"posy", false, false, false},
3825                 {"negy", false, false, false},
3826                 {"posz", false, false, false},
3827                 {"negz", false, false, false}
3828         },
3829         {
3830                 {"rt",    true, false,  true},
3831                 {"lf",   false,  true,  true},
3832                 {"ft",    true,  true, false},
3833                 {"bk",   false, false, false},
3834                 {"up",    true, false,  true},
3835                 {"dn",    true, false,  true}
3836         }
3837 };
3838
3839 static int componentorder[4] = {0, 1, 2, 3};
3840
3841 static rtexture_t *R_LoadCubemap(const char *basename)
3842 {
3843         int i, j, cubemapsize;
3844         unsigned char *cubemappixels, *image_buffer;
3845         rtexture_t *cubemaptexture;
3846         char name[256];
3847         // must start 0 so the first loadimagepixels has no requested width/height
3848         cubemapsize = 0;
3849         cubemappixels = NULL;
3850         cubemaptexture = NULL;
3851         // keep trying different suffix groups (posx, px, rt) until one loads
3852         for (j = 0;j < 3 && !cubemappixels;j++)
3853         {
3854                 // load the 6 images in the suffix group
3855                 for (i = 0;i < 6;i++)
3856                 {
3857                         // generate an image name based on the base and and suffix
3858                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3859                         // load it
3860                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3861                         {
3862                                 // an image loaded, make sure width and height are equal
3863                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3864                                 {
3865                                         // if this is the first image to load successfully, allocate the cubemap memory
3866                                         if (!cubemappixels && image_width >= 1)
3867                                         {
3868                                                 cubemapsize = image_width;
3869                                                 // note this clears to black, so unavailable sides are black
3870                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3871                                         }
3872                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3873                                         if (cubemappixels)
3874                                                 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);
3875                                 }
3876                                 else
3877                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3878                                 // free the image
3879                                 Mem_Free(image_buffer);
3880                         }
3881                 }
3882         }
3883         // if a cubemap loaded, upload it
3884         if (cubemappixels)
3885         {
3886                 if (developer_loading.integer)
3887                         Con_Printf("loading cubemap \"%s\"\n", basename);
3888
3889                 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);
3890                 Mem_Free(cubemappixels);
3891         }
3892         else
3893         {
3894                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3895                 if (developer_loading.integer)
3896                 {
3897                         Con_Printf("(tried tried images ");
3898                         for (j = 0;j < 3;j++)
3899                                 for (i = 0;i < 6;i++)
3900                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3901                         Con_Print(" and was unable to find any of them).\n");
3902                 }
3903         }
3904         return cubemaptexture;
3905 }
3906
3907 rtexture_t *R_GetCubemap(const char *basename)
3908 {
3909         int i;
3910         for (i = 0;i < r_texture_numcubemaps;i++)
3911                 if (r_texture_cubemaps[i] != NULL)
3912                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3913                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3914         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3915                 return r_texture_whitecube;
3916         r_texture_numcubemaps++;
3917         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3918         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3919         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3920         return r_texture_cubemaps[i]->texture;
3921 }
3922
3923 static void R_Main_FreeViewCache(void)
3924 {
3925         if (r_refdef.viewcache.entityvisible)
3926                 Mem_Free(r_refdef.viewcache.entityvisible);
3927         if (r_refdef.viewcache.world_pvsbits)
3928                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3929         if (r_refdef.viewcache.world_leafvisible)
3930                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3931         if (r_refdef.viewcache.world_surfacevisible)
3932                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3933         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3934 }
3935
3936 static void R_Main_ResizeViewCache(void)
3937 {
3938         int numentities = r_refdef.scene.numentities;
3939         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3940         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3941         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3942         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3943         if (r_refdef.viewcache.maxentities < numentities)
3944         {
3945                 r_refdef.viewcache.maxentities = numentities;
3946                 if (r_refdef.viewcache.entityvisible)
3947                         Mem_Free(r_refdef.viewcache.entityvisible);
3948                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3949         }
3950         if (r_refdef.viewcache.world_numclusters != numclusters)
3951         {
3952                 r_refdef.viewcache.world_numclusters = numclusters;
3953                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3954                 if (r_refdef.viewcache.world_pvsbits)
3955                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3956                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3957         }
3958         if (r_refdef.viewcache.world_numleafs != numleafs)
3959         {
3960                 r_refdef.viewcache.world_numleafs = numleafs;
3961                 if (r_refdef.viewcache.world_leafvisible)
3962                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3963                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3964         }
3965         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3966         {
3967                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3968                 if (r_refdef.viewcache.world_surfacevisible)
3969                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3970                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3971         }
3972 }
3973
3974 extern rtexture_t *loadingscreentexture;
3975 static void gl_main_start(void)
3976 {
3977         loadingscreentexture = NULL;
3978         r_texture_blanknormalmap = NULL;
3979         r_texture_white = NULL;
3980         r_texture_grey128 = NULL;
3981         r_texture_black = NULL;
3982         r_texture_whitecube = NULL;
3983         r_texture_normalizationcube = NULL;
3984         r_texture_fogattenuation = NULL;
3985         r_texture_fogheighttexture = NULL;
3986         r_texture_gammaramps = NULL;
3987         r_texture_numcubemaps = 0;
3988         r_uniformbufferalignment = 32;
3989
3990         r_loaddds = r_texture_dds_load.integer != 0;
3991         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3992
3993         switch(vid.renderpath)
3994         {
3995         case RENDERPATH_GL20:
3996         case RENDERPATH_D3D9:
3997         case RENDERPATH_D3D10:
3998         case RENDERPATH_D3D11:
3999         case RENDERPATH_SOFT:
4000         case RENDERPATH_GLES2:
4001                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4002                 Cvar_SetValueQuick(&gl_combine, 1);
4003                 Cvar_SetValueQuick(&r_glsl, 1);
4004                 r_loadnormalmap = true;
4005                 r_loadgloss = true;
4006                 r_loadfog = false;
4007 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4008                 if (vid.support.arb_uniform_buffer_object)
4009                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4010 #endif
4011                         break;
4012         case RENDERPATH_GL13:
4013         case RENDERPATH_GLES1:
4014                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4015                 Cvar_SetValueQuick(&gl_combine, 1);
4016                 Cvar_SetValueQuick(&r_glsl, 0);
4017                 r_loadnormalmap = false;
4018                 r_loadgloss = false;
4019                 r_loadfog = true;
4020                 break;
4021         case RENDERPATH_GL11:
4022                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4023                 Cvar_SetValueQuick(&gl_combine, 0);
4024                 Cvar_SetValueQuick(&r_glsl, 0);
4025                 r_loadnormalmap = false;
4026                 r_loadgloss = false;
4027                 r_loadfog = true;
4028                 break;
4029         }
4030
4031         R_AnimCache_Free();
4032         R_FrameData_Reset();
4033         R_BufferData_Reset();
4034
4035         r_numqueries = 0;
4036         r_maxqueries = 0;
4037         memset(r_queries, 0, sizeof(r_queries));
4038
4039         r_qwskincache = NULL;
4040         r_qwskincache_size = 0;
4041
4042         // due to caching of texture_t references, the collision cache must be reset
4043         Collision_Cache_Reset(true);
4044
4045         // set up r_skinframe loading system for textures
4046         memset(&r_skinframe, 0, sizeof(r_skinframe));
4047         r_skinframe.loadsequence = 1;
4048         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4049
4050         r_main_texturepool = R_AllocTexturePool();
4051         R_BuildBlankTextures();
4052         R_BuildNoTexture();
4053         if (vid.support.arb_texture_cube_map)
4054         {
4055                 R_BuildWhiteCube();
4056                 R_BuildNormalizationCube();
4057         }
4058         r_texture_fogattenuation = NULL;
4059         r_texture_fogheighttexture = NULL;
4060         r_texture_gammaramps = NULL;
4061         //r_texture_fogintensity = NULL;
4062         memset(&r_fb, 0, sizeof(r_fb));
4063         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4064         r_glsl_permutation = NULL;
4065         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4067 #ifdef SUPPORTD3D
4068         r_hlsl_permutation = NULL;
4069         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4070         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4071 #endif
4072         memset(&r_svbsp, 0, sizeof (r_svbsp));
4073
4074         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4075         r_texture_numcubemaps = 0;
4076
4077         r_refdef.fogmasktable_density = 0;
4078
4079 #ifdef __ANDROID__
4080         // For Steelstorm Android
4081         // FIXME CACHE the program and reload
4082         // FIXME see possible combinations for SS:BR android
4083         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4084         R_SetupShader_SetPermutationGLSL(0, 12);
4085         R_SetupShader_SetPermutationGLSL(0, 13);
4086         R_SetupShader_SetPermutationGLSL(0, 8388621);
4087         R_SetupShader_SetPermutationGLSL(3, 0);
4088         R_SetupShader_SetPermutationGLSL(3, 2048);
4089         R_SetupShader_SetPermutationGLSL(5, 0);
4090         R_SetupShader_SetPermutationGLSL(5, 2);
4091         R_SetupShader_SetPermutationGLSL(5, 2048);
4092         R_SetupShader_SetPermutationGLSL(5, 8388608);
4093         R_SetupShader_SetPermutationGLSL(11, 1);
4094         R_SetupShader_SetPermutationGLSL(11, 2049);
4095         R_SetupShader_SetPermutationGLSL(11, 8193);
4096         R_SetupShader_SetPermutationGLSL(11, 10241);
4097         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4098 #endif
4099 }
4100
4101 static void gl_main_shutdown(void)
4102 {
4103         R_RenderTarget_FreeUnused(true);
4104         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4105         R_AnimCache_Free();
4106         R_FrameData_Reset();
4107         R_BufferData_Reset();
4108
4109         R_Main_FreeViewCache();
4110
4111         switch(vid.renderpath)
4112         {
4113         case RENDERPATH_GL11:
4114         case RENDERPATH_GL13:
4115         case RENDERPATH_GL20:
4116         case RENDERPATH_GLES1:
4117         case RENDERPATH_GLES2:
4118 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4119                 if (r_maxqueries)
4120                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4121 #endif
4122                 break;
4123         case RENDERPATH_D3D9:
4124                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4125                 break;
4126         case RENDERPATH_D3D10:
4127                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4128                 break;
4129         case RENDERPATH_D3D11:
4130                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4131                 break;
4132         case RENDERPATH_SOFT:
4133                 break;
4134         }
4135
4136         r_numqueries = 0;
4137         r_maxqueries = 0;
4138         memset(r_queries, 0, sizeof(r_queries));
4139
4140         r_qwskincache = NULL;
4141         r_qwskincache_size = 0;
4142
4143         // clear out the r_skinframe state
4144         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4145         memset(&r_skinframe, 0, sizeof(r_skinframe));
4146
4147         if (r_svbsp.nodes)
4148                 Mem_Free(r_svbsp.nodes);
4149         memset(&r_svbsp, 0, sizeof (r_svbsp));
4150         R_FreeTexturePool(&r_main_texturepool);
4151         loadingscreentexture = NULL;
4152         r_texture_blanknormalmap = NULL;
4153         r_texture_white = NULL;
4154         r_texture_grey128 = NULL;
4155         r_texture_black = NULL;
4156         r_texture_whitecube = NULL;
4157         r_texture_normalizationcube = NULL;
4158         r_texture_fogattenuation = NULL;
4159         r_texture_fogheighttexture = NULL;
4160         r_texture_gammaramps = NULL;
4161         r_texture_numcubemaps = 0;
4162         //r_texture_fogintensity = NULL;
4163         memset(&r_fb, 0, sizeof(r_fb));
4164         R_GLSL_Restart_f();
4165
4166         r_glsl_permutation = NULL;
4167         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4168         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4169 #ifdef SUPPORTD3D
4170         r_hlsl_permutation = NULL;
4171         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4172         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4173 #endif
4174 }
4175
4176 static void gl_main_newmap(void)
4177 {
4178         // FIXME: move this code to client
4179         char *entities, entname[MAX_QPATH];
4180         if (r_qwskincache)
4181                 Mem_Free(r_qwskincache);
4182         r_qwskincache = NULL;
4183         r_qwskincache_size = 0;
4184         if (cl.worldmodel)
4185         {
4186                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4187                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4188                 {
4189                         CL_ParseEntityLump(entities);
4190                         Mem_Free(entities);
4191                         return;
4192                 }
4193                 if (cl.worldmodel->brush.entities)
4194                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4195         }
4196         R_Main_FreeViewCache();
4197
4198         R_FrameData_Reset();
4199         R_BufferData_Reset();
4200 }
4201
4202 void GL_Main_Init(void)
4203 {
4204         int i;
4205         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4206         R_InitShaderModeInfo();
4207
4208         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4209         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4210         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4211         if (gamemode == GAME_NEHAHRA)
4212         {
4213                 Cvar_RegisterVariable (&gl_fogenable);
4214                 Cvar_RegisterVariable (&gl_fogdensity);
4215                 Cvar_RegisterVariable (&gl_fogred);
4216                 Cvar_RegisterVariable (&gl_foggreen);
4217                 Cvar_RegisterVariable (&gl_fogblue);
4218                 Cvar_RegisterVariable (&gl_fogstart);
4219                 Cvar_RegisterVariable (&gl_fogend);
4220                 Cvar_RegisterVariable (&gl_skyclip);
4221         }
4222         Cvar_RegisterVariable(&r_motionblur);
4223         Cvar_RegisterVariable(&r_damageblur);
4224         Cvar_RegisterVariable(&r_motionblur_averaging);
4225         Cvar_RegisterVariable(&r_motionblur_randomize);
4226         Cvar_RegisterVariable(&r_motionblur_minblur);
4227         Cvar_RegisterVariable(&r_motionblur_maxblur);
4228         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4229         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4230         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4231         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4232         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4233         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4234         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4235         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4236         Cvar_RegisterVariable(&r_equalize_entities_by);
4237         Cvar_RegisterVariable(&r_equalize_entities_to);
4238         Cvar_RegisterVariable(&r_depthfirst);
4239         Cvar_RegisterVariable(&r_useinfinitefarclip);
4240         Cvar_RegisterVariable(&r_farclip_base);
4241         Cvar_RegisterVariable(&r_farclip_world);
4242         Cvar_RegisterVariable(&r_nearclip);
4243         Cvar_RegisterVariable(&r_deformvertexes);
4244         Cvar_RegisterVariable(&r_transparent);
4245         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4246         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4247         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4248         Cvar_RegisterVariable(&r_showoverdraw);
4249         Cvar_RegisterVariable(&r_showbboxes);
4250         Cvar_RegisterVariable(&r_showbboxes_client);
4251         Cvar_RegisterVariable(&r_showsurfaces);
4252         Cvar_RegisterVariable(&r_showtris);
4253         Cvar_RegisterVariable(&r_shownormals);
4254         Cvar_RegisterVariable(&r_showlighting);
4255         Cvar_RegisterVariable(&r_showshadowvolumes);
4256         Cvar_RegisterVariable(&r_showcollisionbrushes);
4257         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4258         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4259         Cvar_RegisterVariable(&r_showdisabledepthtest);
4260         Cvar_RegisterVariable(&r_drawportals);
4261         Cvar_RegisterVariable(&r_drawentities);
4262         Cvar_RegisterVariable(&r_draw2d);
4263         Cvar_RegisterVariable(&r_drawworld);
4264         Cvar_RegisterVariable(&r_cullentities_trace);
4265         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4266         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4267         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4268         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4269         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4270         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4271         Cvar_RegisterVariable(&r_sortentities);
4272         Cvar_RegisterVariable(&r_drawviewmodel);
4273         Cvar_RegisterVariable(&r_drawexteriormodel);
4274         Cvar_RegisterVariable(&r_speeds);
4275         Cvar_RegisterVariable(&r_fullbrights);
4276         Cvar_RegisterVariable(&r_wateralpha);
4277         Cvar_RegisterVariable(&r_dynamic);
4278         Cvar_RegisterVariable(&r_fakelight);
4279         Cvar_RegisterVariable(&r_fakelight_intensity);
4280         Cvar_RegisterVariable(&r_fullbright_directed);
4281         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4282         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4283         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4284         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4285         Cvar_RegisterVariable(&r_fullbright);
4286         Cvar_RegisterVariable(&r_shadows);
4287         Cvar_RegisterVariable(&r_shadows_darken);
4288         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4289         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4290         Cvar_RegisterVariable(&r_shadows_throwdistance);
4291         Cvar_RegisterVariable(&r_shadows_throwdirection);
4292         Cvar_RegisterVariable(&r_shadows_focus);
4293         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4294         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4295         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4296         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4297         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4298         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4299         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4300         Cvar_RegisterVariable(&r_fog_exp2);
4301         Cvar_RegisterVariable(&r_fog_clear);
4302         Cvar_RegisterVariable(&r_drawfog);
4303         Cvar_RegisterVariable(&r_transparentdepthmasking);
4304         Cvar_RegisterVariable(&r_transparent_sortmindist);
4305         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4306         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4307         Cvar_RegisterVariable(&r_texture_dds_load);
4308         Cvar_RegisterVariable(&r_texture_dds_save);
4309         Cvar_RegisterVariable(&r_textureunits);
4310         Cvar_RegisterVariable(&gl_combine);
4311         Cvar_RegisterVariable(&r_usedepthtextures);
4312         Cvar_RegisterVariable(&r_viewfbo);
4313         Cvar_RegisterVariable(&r_rendertarget_debug);
4314         Cvar_RegisterVariable(&r_viewscale);
4315         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4316         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4317         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4318         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4319         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4320         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4321         Cvar_RegisterVariable(&r_glsl);
4322         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4323         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4324         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4325         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4326         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4327         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4328         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4329         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4330         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4331         Cvar_RegisterVariable(&r_glsl_postprocess);
4332         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4333         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4334         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4335         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4336         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4337         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4338         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4339         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4340         Cvar_RegisterVariable(&r_celshading);
4341         Cvar_RegisterVariable(&r_celoutlines);
4342
4343         Cvar_RegisterVariable(&r_water);
4344         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4345         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4346         Cvar_RegisterVariable(&r_water_clippingplanebias);
4347         Cvar_RegisterVariable(&r_water_refractdistort);
4348         Cvar_RegisterVariable(&r_water_reflectdistort);
4349         Cvar_RegisterVariable(&r_water_scissormode);
4350         Cvar_RegisterVariable(&r_water_lowquality);
4351         Cvar_RegisterVariable(&r_water_hideplayer);
4352
4353         Cvar_RegisterVariable(&r_lerpsprites);
4354         Cvar_RegisterVariable(&r_lerpmodels);
4355         Cvar_RegisterVariable(&r_lerplightstyles);
4356         Cvar_RegisterVariable(&r_waterscroll);
4357         Cvar_RegisterVariable(&r_bloom);
4358         Cvar_RegisterVariable(&r_bloom_colorscale);
4359         Cvar_RegisterVariable(&r_bloom_brighten);
4360         Cvar_RegisterVariable(&r_bloom_blur);
4361         Cvar_RegisterVariable(&r_bloom_resolution);
4362         Cvar_RegisterVariable(&r_bloom_colorexponent);
4363         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4364         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4365         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4366         Cvar_RegisterVariable(&r_hdr_glowintensity);
4367         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4368         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4369         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4370         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4371         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4372         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4373         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4374         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4375         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4376         Cvar_RegisterVariable(&developer_texturelogging);
4377         Cvar_RegisterVariable(&gl_lightmaps);
4378         Cvar_RegisterVariable(&r_test);
4379         Cvar_RegisterVariable(&r_batch_multidraw);
4380         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4381         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4382         Cvar_RegisterVariable(&r_glsl_skeletal);
4383         Cvar_RegisterVariable(&r_glsl_saturation);
4384         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4385         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4386         Cvar_RegisterVariable(&r_framedatasize);
4387         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4388                 Cvar_RegisterVariable(&r_buffermegs[i]);
4389         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4390         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4391                 Cvar_SetValue("r_fullbrights", 0);
4392 #ifdef DP_MOBILETOUCH
4393         // GLES devices have terrible depth precision in general, so...
4394         Cvar_SetValueQuick(&r_nearclip, 4);
4395         Cvar_SetValueQuick(&r_farclip_base, 4096);
4396         Cvar_SetValueQuick(&r_farclip_world, 0);
4397         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4398 #endif
4399         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4400 }
4401
4402 void Render_Init(void)
4403 {
4404         gl_backend_init();
4405         R_Textures_Init();
4406         GL_Main_Init();
4407         Font_Init();
4408         GL_Draw_Init();
4409         R_Shadow_Init();
4410         R_Sky_Init();
4411         GL_Surf_Init();
4412         Sbar_Init();
4413         R_Particles_Init();
4414         R_Explosion_Init();
4415         R_LightningBeams_Init();
4416         Mod_RenderInit();
4417 }
4418
4419 /*
4420 ===============
4421 GL_Init
4422 ===============
4423 */
4424 #ifndef USE_GLES2
4425 extern char *ENGINE_EXTENSIONS;
4426 void GL_Init (void)
4427 {
4428         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4429         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4430         gl_version = (const char *)qglGetString(GL_VERSION);
4431         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4432
4433         if (!gl_extensions)
4434                 gl_extensions = "";
4435         if (!gl_platformextensions)
4436                 gl_platformextensions = "";
4437
4438         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4439         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4440         Con_Printf("GL_VERSION: %s\n", gl_version);
4441         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4442         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4443
4444         VID_CheckExtensions();
4445
4446         // LordHavoc: report supported extensions
4447 #ifdef CONFIG_MENU
4448         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4449 #else
4450         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4451 #endif
4452
4453         // clear to black (loading plaque will be seen over this)
4454         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4455 }
4456 #endif
4457
4458 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4459 {
4460         int i;
4461         mplane_t *p;
4462         if (r_trippy.integer)
4463                 return false;
4464         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4465         {
4466                 p = r_refdef.view.frustum + i;
4467                 switch(p->signbits)
4468                 {
4469                 default:
4470                 case 0:
4471                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 1:
4475                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 2:
4479                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 3:
4483                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 4:
4487                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 5:
4491                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 6:
4495                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 7:
4499                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 }
4503         }
4504         return false;
4505 }
4506
4507 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4508 {
4509         int i;
4510         const mplane_t *p;
4511         if (r_trippy.integer)
4512                 return false;
4513         for (i = 0;i < numplanes;i++)
4514         {
4515                 p = planes + i;
4516                 switch(p->signbits)
4517                 {
4518                 default:
4519                 case 0:
4520                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 1:
4524                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 2:
4528                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 case 3:
4532                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4533                                 return true;
4534                         break;
4535                 case 4:
4536                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4537                                 return true;
4538                         break;
4539                 case 5:
4540                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4541                                 return true;
4542                         break;
4543                 case 6:
4544                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4545                                 return true;
4546                         break;
4547                 case 7:
4548                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4549                                 return true;
4550                         break;
4551                 }
4552         }
4553         return false;
4554 }
4555
4556 //==================================================================================
4557
4558 // LordHavoc: this stores temporary data used within the same frame
4559
4560 typedef struct r_framedata_mem_s
4561 {
4562         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4563         size_t size; // how much usable space
4564         size_t current; // how much space in use
4565         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4566         size_t wantedsize; // how much space was allocated
4567         unsigned char *data; // start of real data (16byte aligned)
4568 }
4569 r_framedata_mem_t;
4570
4571 static r_framedata_mem_t *r_framedata_mem;
4572
4573 void R_FrameData_Reset(void)
4574 {
4575         while (r_framedata_mem)
4576         {
4577                 r_framedata_mem_t *next = r_framedata_mem->purge;
4578                 Mem_Free(r_framedata_mem);
4579                 r_framedata_mem = next;
4580         }
4581 }
4582
4583 static void R_FrameData_Resize(qboolean mustgrow)
4584 {
4585         size_t wantedsize;
4586         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4587         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4588         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4589         {
4590                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4591                 newmem->wantedsize = wantedsize;
4592                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4593                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4594                 newmem->current = 0;
4595                 newmem->mark = 0;
4596                 newmem->purge = r_framedata_mem;
4597                 r_framedata_mem = newmem;
4598         }
4599 }
4600
4601 void R_FrameData_NewFrame(void)
4602 {
4603         R_FrameData_Resize(false);
4604         if (!r_framedata_mem)
4605                 return;
4606         // if we ran out of space on the last frame, free the old memory now
4607         while (r_framedata_mem->purge)
4608         {
4609                 // repeatedly remove the second item in the list, leaving only head
4610                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4611                 Mem_Free(r_framedata_mem->purge);
4612                 r_framedata_mem->purge = next;
4613         }
4614         // reset the current mem pointer
4615         r_framedata_mem->current = 0;
4616         r_framedata_mem->mark = 0;
4617 }
4618
4619 void *R_FrameData_Alloc(size_t size)
4620 {
4621         void *data;
4622         float newvalue;
4623
4624         // align to 16 byte boundary - the data pointer is already aligned, so we
4625         // only need to ensure the size of every allocation is also aligned
4626         size = (size + 15) & ~15;
4627
4628         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4629         {
4630                 // emergency - we ran out of space, allocate more memory
4631                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4632                 newvalue = r_framedatasize.value * 2.0f;
4633                 // 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
4634                 if (sizeof(size_t) >= 8)
4635                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4636                 else
4637                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4638                 // this might not be a growing it, but we'll allocate another buffer every time
4639                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4640                 R_FrameData_Resize(true);
4641         }
4642
4643         data = r_framedata_mem->data + r_framedata_mem->current;
4644         r_framedata_mem->current += size;
4645
4646         // count the usage for stats
4647         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4648         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4649
4650         return (void *)data;
4651 }
4652
4653 void *R_FrameData_Store(size_t size, void *data)
4654 {
4655         void *d = R_FrameData_Alloc(size);
4656         if (d && data)
4657                 memcpy(d, data, size);
4658         return d;
4659 }
4660
4661 void R_FrameData_SetMark(void)
4662 {
4663         if (!r_framedata_mem)
4664                 return;
4665         r_framedata_mem->mark = r_framedata_mem->current;
4666 }
4667
4668 void R_FrameData_ReturnToMark(void)
4669 {
4670         if (!r_framedata_mem)
4671                 return;
4672         r_framedata_mem->current = r_framedata_mem->mark;
4673 }
4674
4675 //==================================================================================
4676
4677 // avoid reusing the same buffer objects on consecutive frames
4678 #define R_BUFFERDATA_CYCLE 3
4679
4680 typedef struct r_bufferdata_buffer_s
4681 {
4682         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4683         size_t size; // how much usable space
4684         size_t current; // how much space in use
4685         r_meshbuffer_t *buffer; // the buffer itself
4686 }
4687 r_bufferdata_buffer_t;
4688
4689 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4690 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4691
4692 /// frees all dynamic buffers
4693 void R_BufferData_Reset(void)
4694 {
4695         int cycle, type;
4696         r_bufferdata_buffer_t **p, *mem;
4697         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4698         {
4699                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4700                 {
4701                         // free all buffers
4702                         p = &r_bufferdata_buffer[cycle][type];
4703                         while (*p)
4704                         {
4705                                 mem = *p;
4706                                 *p = (*p)->purge;
4707                                 if (mem->buffer)
4708                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4709                                 Mem_Free(mem);
4710                         }
4711                 }
4712         }
4713 }
4714
4715 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4716 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4717 {
4718         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4719         size_t size;
4720         float newvalue = r_buffermegs[type].value;
4721
4722         // increase the cvar if we have to (but only if we already have a mem)
4723         if (mustgrow && mem)
4724                 newvalue *= 2.0f;
4725         newvalue = bound(0.25f, newvalue, 256.0f);
4726         while (newvalue * 1024*1024 < minsize)
4727                 newvalue *= 2.0f;
4728
4729         // clamp the cvar to valid range
4730         newvalue = bound(0.25f, newvalue, 256.0f);
4731         if (r_buffermegs[type].value != newvalue)
4732                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4733
4734         // calculate size in bytes
4735         size = (size_t)(newvalue * 1024*1024);
4736         size = bound(131072, size, 256*1024*1024);
4737
4738         // allocate a new buffer if the size is different (purge old one later)
4739         // or if we were told we must grow the buffer
4740         if (!mem || mem->size != size || mustgrow)
4741         {
4742                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4743                 mem->size = size;
4744                 mem->current = 0;
4745                 if (type == R_BUFFERDATA_VERTEX)
4746                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4747                 else if (type == R_BUFFERDATA_INDEX16)
4748                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4749                 else if (type == R_BUFFERDATA_INDEX32)
4750                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4751                 else if (type == R_BUFFERDATA_UNIFORM)
4752                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4753                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4754                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4755         }
4756 }
4757
4758 void R_BufferData_NewFrame(void)
4759 {
4760         int type;
4761         r_bufferdata_buffer_t **p, *mem;
4762         // cycle to the next frame's buffers
4763         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4764         // if we ran out of space on the last time we used these buffers, free the old memory now
4765         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4766         {
4767                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4768                 {
4769                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4770                         // free all but the head buffer, this is how we recycle obsolete
4771                         // buffers after they are no longer in use
4772                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4773                         while (*p)
4774                         {
4775                                 mem = *p;
4776                                 *p = (*p)->purge;
4777                                 if (mem->buffer)
4778                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4779                                 Mem_Free(mem);
4780                         }
4781                         // reset the current offset
4782                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4783                 }
4784         }
4785 }
4786
4787 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4788 {
4789         r_bufferdata_buffer_t *mem;
4790         int offset = 0;
4791         int padsize;
4792
4793         *returnbufferoffset = 0;
4794
4795         // align size to a byte boundary appropriate for the buffer type, this
4796         // makes all allocations have aligned start offsets
4797         if (type == R_BUFFERDATA_UNIFORM)
4798                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4799         else
4800                 padsize = (datasize + 15) & ~15;
4801
4802         // if we ran out of space in this buffer we must allocate a new one
4803         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)
4804                 R_BufferData_Resize(type, true, padsize);
4805
4806         // if the resize did not give us enough memory, fail
4807         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)
4808                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4809
4810         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4811         offset = (int)mem->current;
4812         mem->current += padsize;
4813
4814         // upload the data to the buffer at the chosen offset
4815         if (offset == 0)
4816                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4817         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4818
4819         // count the usage for stats
4820         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4821         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4822
4823         // return the buffer offset
4824         *returnbufferoffset = offset;
4825
4826         return mem->buffer;
4827 }
4828
4829 //==================================================================================
4830
4831 // LordHavoc: animcache originally written by Echon, rewritten since then
4832
4833 /**
4834  * Animation cache prevents re-generating mesh data for an animated model
4835  * multiple times in one frame for lighting, shadowing, reflections, etc.
4836  */
4837
4838 void R_AnimCache_Free(void)
4839 {
4840 }
4841
4842 void R_AnimCache_ClearCache(void)
4843 {
4844         int i;
4845         entity_render_t *ent;
4846
4847         for (i = 0;i < r_refdef.scene.numentities;i++)
4848         {
4849                 ent = r_refdef.scene.entities[i];
4850                 ent->animcache_vertex3f = NULL;
4851                 ent->animcache_vertex3f_vertexbuffer = NULL;
4852                 ent->animcache_vertex3f_bufferoffset = 0;
4853                 ent->animcache_normal3f = NULL;
4854                 ent->animcache_normal3f_vertexbuffer = NULL;
4855                 ent->animcache_normal3f_bufferoffset = 0;
4856                 ent->animcache_svector3f = NULL;
4857                 ent->animcache_svector3f_vertexbuffer = NULL;
4858                 ent->animcache_svector3f_bufferoffset = 0;
4859                 ent->animcache_tvector3f = NULL;
4860                 ent->animcache_tvector3f_vertexbuffer = NULL;
4861                 ent->animcache_tvector3f_bufferoffset = 0;
4862                 ent->animcache_vertexmesh = NULL;
4863                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4864                 ent->animcache_vertexmesh_bufferoffset = 0;
4865                 ent->animcache_skeletaltransform3x4 = NULL;
4866                 ent->animcache_skeletaltransform3x4buffer = NULL;
4867                 ent->animcache_skeletaltransform3x4offset = 0;
4868                 ent->animcache_skeletaltransform3x4size = 0;
4869         }
4870 }
4871
4872 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4873 {
4874         int i;
4875
4876         // check if we need the meshbuffers
4877         if (!vid.useinterleavedarrays)
4878                 return;
4879
4880         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4881                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4882         // TODO: upload vertexbuffer?
4883         if (ent->animcache_vertexmesh)
4884         {
4885                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4886                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4887                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4888                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4889                 for (i = 0;i < numvertices;i++)
4890                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4891                 if (ent->animcache_svector3f)
4892                         for (i = 0;i < numvertices;i++)
4893                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4894                 if (ent->animcache_tvector3f)
4895                         for (i = 0;i < numvertices;i++)
4896                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4897                 if (ent->animcache_normal3f)
4898                         for (i = 0;i < numvertices;i++)
4899                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4900         }
4901 }
4902
4903 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4904 {
4905         dp_model_t *model = ent->model;
4906         int numvertices;
4907
4908         // see if this ent is worth caching
4909         if (!model || !model->Draw || !model->AnimateVertices)
4910                 return false;
4911         // nothing to cache if it contains no animations and has no skeleton
4912         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4913                 return false;
4914         // see if it is already cached for gpuskeletal
4915         if (ent->animcache_skeletaltransform3x4)
4916                 return false;
4917         // see if it is already cached as a mesh
4918         if (ent->animcache_vertex3f)
4919         {
4920                 // check if we need to add normals or tangents
4921                 if (ent->animcache_normal3f)
4922                         wantnormals = false;
4923                 if (ent->animcache_svector3f)
4924                         wanttangents = false;
4925                 if (!wantnormals && !wanttangents)
4926                         return false;
4927         }
4928
4929         // check which kind of cache we need to generate
4930         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4931         {
4932                 // cache the skeleton so the vertex shader can use it
4933                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4934                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4935                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4936                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4937                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4938                 // note: this can fail if the buffer is at the grow limit
4939                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4940                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4941         }
4942         else if (ent->animcache_vertex3f)
4943         {
4944                 // mesh was already cached but we may need to add normals/tangents
4945                 // (this only happens with multiple views, reflections, cameras, etc)
4946                 if (wantnormals || wanttangents)
4947                 {
4948                         numvertices = model->surfmesh.num_vertices;
4949                         if (wantnormals)
4950                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4951                         if (wanttangents)
4952                         {
4953                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4954                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4955                         }
4956                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4957                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4958                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4959                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4960                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4961                 }
4962         }
4963         else
4964         {
4965                 // generate mesh cache
4966                 numvertices = model->surfmesh.num_vertices;
4967                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4968                 if (wantnormals)
4969                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4970                 if (wanttangents)
4971                 {
4972                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4974                 }
4975                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4976                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4977                 if (wantnormals || wanttangents)
4978                 {
4979                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4980                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4981                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4982                 }
4983                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4984                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4985                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4986         }
4987         return true;
4988 }
4989
4990 void R_AnimCache_CacheVisibleEntities(void)
4991 {
4992         int i;
4993         qboolean wantnormals = true;
4994         qboolean wanttangents = !r_showsurfaces.integer;
4995
4996         switch(vid.renderpath)
4997         {
4998         case RENDERPATH_GL20:
4999         case RENDERPATH_D3D9:
5000         case RENDERPATH_D3D10:
5001         case RENDERPATH_D3D11:
5002         case RENDERPATH_GLES2:
5003                 break;
5004         case RENDERPATH_GL11:
5005         case RENDERPATH_GL13:
5006         case RENDERPATH_GLES1:
5007                 wanttangents = false;
5008                 break;
5009         case RENDERPATH_SOFT:
5010                 break;
5011         }
5012
5013         if (r_shownormals.integer)
5014                 wanttangents = wantnormals = true;
5015
5016         // TODO: thread this
5017         // NOTE: R_PrepareRTLights() also caches entities
5018
5019         for (i = 0;i < r_refdef.scene.numentities;i++)
5020                 if (r_refdef.viewcache.entityvisible[i])
5021                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5022 }
5023
5024 //==================================================================================
5025
5026 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5027 {
5028         int i;
5029         vec3_t eyemins, eyemaxs;
5030         vec3_t boxmins, boxmaxs;
5031         vec3_t start;
5032         vec3_t end;
5033         dp_model_t *model = r_refdef.scene.worldmodel;
5034         static vec3_t positions[] = {
5035                 { 0.5f, 0.5f, 0.5f },
5036                 { 0.0f, 0.0f, 0.0f },
5037                 { 0.0f, 0.0f, 1.0f },
5038                 { 0.0f, 1.0f, 0.0f },
5039                 { 0.0f, 1.0f, 1.0f },
5040                 { 1.0f, 0.0f, 0.0f },
5041                 { 1.0f, 0.0f, 1.0f },
5042                 { 1.0f, 1.0f, 0.0f },
5043                 { 1.0f, 1.0f, 1.0f },
5044         };
5045
5046         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5047         if (numsamples < 0)
5048                 return true;
5049
5050         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5051         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5052                 return true;
5053
5054         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5055                 return true;
5056
5057         // expand the eye box a little
5058         eyemins[0] = eye[0] - eyejitter;
5059         eyemaxs[0] = eye[0] + eyejitter;
5060         eyemins[1] = eye[1] - eyejitter;
5061         eyemaxs[1] = eye[1] + eyejitter;
5062         eyemins[2] = eye[2] - eyejitter;
5063         eyemaxs[2] = eye[2] + eyejitter;
5064         // expand the box a little
5065         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5066         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5067         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5068         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5069         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5070         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5071
5072         // return true if eye overlaps enlarged box
5073         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5074                 return true;
5075
5076         // try specific positions in the box first - note that these can be cached
5077         if (r_cullentities_trace_entityocclusion.integer)
5078         {
5079                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5080                 {
5081                         VectorCopy(eye, start);
5082                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5083                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5084                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5085                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5086                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5087                         // not picky - if the trace ended anywhere in the box we're good
5088                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5089                                 return true;
5090                 }
5091         }
5092         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5093                 return true;
5094
5095         // try various random positions
5096         for (i = 0; i < numsamples; i++)
5097         {
5098                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5099                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5100                 if (r_cullentities_trace_entityocclusion.integer)
5101                 {
5102                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5103                         // not picky - if the trace ended anywhere in the box we're good
5104                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5105                                 return true;
5106                 }
5107                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5108                         return true;
5109         }
5110
5111         return false;
5112 }
5113
5114
5115 static void R_View_UpdateEntityVisible (void)
5116 {
5117         int i;
5118         int renderimask;
5119         int samples;
5120         entity_render_t *ent;
5121
5122         if (r_refdef.envmap || r_fb.water.hideplayer)
5123                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5124         else if (chase_active.integer || r_fb.water.renderingscene)
5125                 renderimask = RENDER_VIEWMODEL;
5126         else
5127                 renderimask = RENDER_EXTERIORMODEL;
5128         if (!r_drawviewmodel.integer)
5129                 renderimask |= RENDER_VIEWMODEL;
5130         if (!r_drawexteriormodel.integer)
5131                 renderimask |= RENDER_EXTERIORMODEL;
5132         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5133         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5134         {
5135                 // worldmodel can check visibility
5136                 for (i = 0;i < r_refdef.scene.numentities;i++)
5137                 {
5138                         ent = r_refdef.scene.entities[i];
5139                         if (!(ent->flags & renderimask))
5140                         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)))
5141                         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))
5142                                 r_refdef.viewcache.entityvisible[i] = true;
5143                 }
5144         }
5145         else
5146         {
5147                 // no worldmodel or it can't check visibility
5148                 for (i = 0;i < r_refdef.scene.numentities;i++)
5149                 {
5150                         ent = r_refdef.scene.entities[i];
5151                         if (!(ent->flags & renderimask))
5152                         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)))
5153                                 r_refdef.viewcache.entityvisible[i] = true;
5154                 }
5155         }
5156         if (r_cullentities_trace.integer)
5157         {
5158                 for (i = 0;i < r_refdef.scene.numentities;i++)
5159                 {
5160                         if (!r_refdef.viewcache.entityvisible[i])
5161                                 continue;
5162                         ent = r_refdef.scene.entities[i];
5163                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5164                         {
5165                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5166                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5167                                         ent->last_trace_visibility = realtime;
5168                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5169                                         r_refdef.viewcache.entityvisible[i] = 0;
5170                         }
5171                 }
5172         }
5173 }
5174
5175 /// only used if skyrendermasked, and normally returns false
5176 static int R_DrawBrushModelsSky (void)
5177 {
5178         int i, sky;
5179         entity_render_t *ent;
5180
5181         sky = false;
5182         for (i = 0;i < r_refdef.scene.numentities;i++)
5183         {
5184                 if (!r_refdef.viewcache.entityvisible[i])
5185                         continue;
5186                 ent = r_refdef.scene.entities[i];
5187                 if (!ent->model || !ent->model->DrawSky)
5188                         continue;
5189                 ent->model->DrawSky(ent);
5190                 sky = true;
5191         }
5192         return sky;
5193 }
5194
5195 static void R_DrawNoModel(entity_render_t *ent);
5196 static void R_DrawModels(void)
5197 {
5198         int i;
5199         entity_render_t *ent;
5200
5201         for (i = 0;i < r_refdef.scene.numentities;i++)
5202         {
5203                 if (!r_refdef.viewcache.entityvisible[i])
5204                         continue;
5205                 ent = r_refdef.scene.entities[i];
5206                 r_refdef.stats[r_stat_entities]++;
5207                 /*
5208                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5209                 {
5210                         vec3_t f, l, u, o;
5211                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5212                         Con_Printf("R_DrawModels\n");
5213                         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]);
5214                         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);
5215                         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);
5216                 }
5217                 */
5218                 if (ent->model && ent->model->Draw != NULL)
5219                         ent->model->Draw(ent);
5220                 else
5221                         R_DrawNoModel(ent);
5222         }
5223 }
5224
5225 static void R_DrawModelsDepth(void)
5226 {
5227         int i;
5228         entity_render_t *ent;
5229
5230         for (i = 0;i < r_refdef.scene.numentities;i++)
5231         {
5232                 if (!r_refdef.viewcache.entityvisible[i])
5233                         continue;
5234                 ent = r_refdef.scene.entities[i];
5235                 if (ent->model && ent->model->DrawDepth != NULL)
5236                         ent->model->DrawDepth(ent);
5237         }
5238 }
5239
5240 static void R_DrawModelsDebug(void)
5241 {
5242         int i;
5243         entity_render_t *ent;
5244
5245         for (i = 0;i < r_refdef.scene.numentities;i++)
5246         {
5247                 if (!r_refdef.viewcache.entityvisible[i])
5248                         continue;
5249                 ent = r_refdef.scene.entities[i];
5250                 if (ent->model && ent->model->DrawDebug != NULL)
5251                         ent->model->DrawDebug(ent);
5252         }
5253 }
5254
5255 static void R_DrawModelsAddWaterPlanes(void)
5256 {
5257         int i;
5258         entity_render_t *ent;
5259
5260         for (i = 0;i < r_refdef.scene.numentities;i++)
5261         {
5262                 if (!r_refdef.viewcache.entityvisible[i])
5263                         continue;
5264                 ent = r_refdef.scene.entities[i];
5265                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5266                         ent->model->DrawAddWaterPlanes(ent);
5267         }
5268 }
5269
5270 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}};
5271
5272 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5273 {
5274         if (r_hdr_irisadaptation.integer)
5275         {
5276                 vec3_t p;
5277                 vec3_t ambient;
5278                 vec3_t diffuse;
5279                 vec3_t diffusenormal;
5280                 vec3_t forward;
5281                 vec_t brightness = 0.0f;
5282                 vec_t goal;
5283                 vec_t current;
5284                 vec_t d;
5285                 int c;
5286                 VectorCopy(r_refdef.view.forward, forward);
5287                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5288                 {
5289                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5290                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5291                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5292                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5293                         d = DotProduct(forward, diffusenormal);
5294                         brightness += VectorLength(ambient);
5295                         if (d > 0)
5296                                 brightness += d * VectorLength(diffuse);
5297                 }
5298                 brightness *= 1.0f / c;
5299                 brightness += 0.00001f; // make sure it's never zero
5300                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5301                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5302                 current = r_hdr_irisadaptation_value.value;
5303                 if (current < goal)
5304                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5305                 else if (current > goal)
5306                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5307                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5308                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5309         }
5310         else if (r_hdr_irisadaptation_value.value != 1.0f)
5311                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5312 }
5313
5314 static void R_View_SetFrustum(const int *scissor)
5315 {
5316         int i;
5317         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5318         vec3_t forward, left, up, origin, v;
5319
5320         if(scissor)
5321         {
5322                 // flipped x coordinates (because x points left here)
5323                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5324                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5325
5326                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5327                 switch(vid.renderpath)
5328                 {
5329                         case RENDERPATH_D3D9:
5330                         case RENDERPATH_D3D10:
5331                         case RENDERPATH_D3D11:
5332                                 // non-flipped y coordinates
5333                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5334                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5335                                 break;
5336                         case RENDERPATH_SOFT:
5337                         case RENDERPATH_GL11:
5338                         case RENDERPATH_GL13:
5339                         case RENDERPATH_GL20:
5340                         case RENDERPATH_GLES1:
5341                         case RENDERPATH_GLES2:
5342                                 // non-flipped y coordinates
5343                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5344                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5345                                 break;
5346                 }
5347         }
5348
5349         // we can't trust r_refdef.view.forward and friends in reflected scenes
5350         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5351
5352 #if 0
5353         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5354         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5355         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5356         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5357         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5358         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5359         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5360         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5361         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5362         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5363         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5364         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5365 #endif
5366
5367 #if 0
5368         zNear = r_refdef.nearclip;
5369         nudge = 1.0 - 1.0 / (1<<23);
5370         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5371         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5372         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5373         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5374         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5375         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5376         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5377         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5378 #endif
5379
5380
5381
5382 #if 0
5383         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5384         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5385         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5386         r_refdef.view.frustum[0].dist = m[15] - m[12];
5387
5388         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5389         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5390         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5391         r_refdef.view.frustum[1].dist = m[15] + m[12];
5392
5393         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5394         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5395         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5396         r_refdef.view.frustum[2].dist = m[15] - m[13];
5397
5398         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5399         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5400         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5401         r_refdef.view.frustum[3].dist = m[15] + m[13];
5402
5403         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5404         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5405         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5406         r_refdef.view.frustum[4].dist = m[15] - m[14];
5407
5408         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5409         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5410         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5411         r_refdef.view.frustum[5].dist = m[15] + m[14];
5412 #endif
5413
5414         if (r_refdef.view.useperspective)
5415         {
5416                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5417                 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]);
5418                 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]);
5419                 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]);
5420                 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]);
5421
5422                 // then the normals from the corners relative to origin
5423                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5424                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5425                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5426                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5427
5428                 // in a NORMAL view, forward cross left == up
5429                 // in a REFLECTED view, forward cross left == down
5430                 // so our cross products above need to be adjusted for a left handed coordinate system
5431                 CrossProduct(forward, left, v);
5432                 if(DotProduct(v, up) < 0)
5433                 {
5434                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5435                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5436                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5437                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5438                 }
5439
5440                 // Leaving those out was a mistake, those were in the old code, and they
5441                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5442                 // I couldn't reproduce it after adding those normalizations. --blub
5443                 VectorNormalize(r_refdef.view.frustum[0].normal);
5444                 VectorNormalize(r_refdef.view.frustum[1].normal);
5445                 VectorNormalize(r_refdef.view.frustum[2].normal);
5446                 VectorNormalize(r_refdef.view.frustum[3].normal);
5447
5448                 // make the corners absolute
5449                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5450                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5451                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5452                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5453
5454                 // one more normal
5455                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5456
5457                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5458                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5459                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5460                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5461                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5462         }
5463         else
5464         {
5465                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5466                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5467                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5468                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5469                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5470                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5471                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5472                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5473                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5474                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5475         }
5476         r_refdef.view.numfrustumplanes = 5;
5477
5478         if (r_refdef.view.useclipplane)
5479         {
5480                 r_refdef.view.numfrustumplanes = 6;
5481                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5482         }
5483
5484         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5485                 PlaneClassify(r_refdef.view.frustum + i);
5486
5487         // LordHavoc: note to all quake engine coders, Quake had a special case
5488         // for 90 degrees which assumed a square view (wrong), so I removed it,
5489         // Quake2 has it disabled as well.
5490
5491         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5492         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5493         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5494         //PlaneClassify(&frustum[0]);
5495
5496         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5497         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5498         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5499         //PlaneClassify(&frustum[1]);
5500
5501         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5502         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5503         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5504         //PlaneClassify(&frustum[2]);
5505
5506         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5507         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5508         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5509         //PlaneClassify(&frustum[3]);
5510
5511         // nearclip plane
5512         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5513         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5514         //PlaneClassify(&frustum[4]);
5515 }
5516
5517 static void R_View_UpdateWithScissor(const int *myscissor)
5518 {
5519         R_Main_ResizeViewCache();
5520         R_View_SetFrustum(myscissor);
5521         R_View_WorldVisibility(r_refdef.view.useclipplane);
5522         R_View_UpdateEntityVisible();
5523 }
5524
5525 static void R_View_Update(void)
5526 {
5527         R_Main_ResizeViewCache();
5528         R_View_SetFrustum(NULL);
5529         R_View_WorldVisibility(r_refdef.view.useclipplane);
5530         R_View_UpdateEntityVisible();
5531 }
5532
5533 float viewscalefpsadjusted = 1.0f;
5534
5535 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5536 {
5537         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5538         scale = bound(0.03125f, scale, 1.0f);
5539         *outwidth = (int)ceil(width * scale);
5540         *outheight = (int)ceil(height * scale);
5541 }
5542
5543 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5544 {
5545         const float *customclipplane = NULL;
5546         float plane[4];
5547         int /*rtwidth,*/ rtheight;
5548         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5549         {
5550                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5551                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5552                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5553                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5554                         dist = r_refdef.view.clipplane.dist;
5555                 plane[0] = r_refdef.view.clipplane.normal[0];
5556                 plane[1] = r_refdef.view.clipplane.normal[1];
5557                 plane[2] = r_refdef.view.clipplane.normal[2];
5558                 plane[3] = -dist;
5559                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5560         }
5561
5562         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5563         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5564
5565         if (!r_refdef.view.useperspective)
5566                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5567         else if (vid.stencil && r_useinfinitefarclip.integer)
5568                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5569         else
5570                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5571         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5572         R_SetViewport(&r_refdef.view.viewport);
5573         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5574         {
5575                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5576                 float screenplane[4];
5577                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5578                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5579                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5580                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5581                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5582         }
5583 }
5584
5585 void R_EntityMatrix(const matrix4x4_t *matrix)
5586 {
5587         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5588         {
5589                 gl_modelmatrixchanged = false;
5590                 gl_modelmatrix = *matrix;
5591                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5592                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5593                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5594                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5595                 CHECKGLERROR
5596                 switch(vid.renderpath)
5597                 {
5598                 case RENDERPATH_D3D9:
5599 #ifdef SUPPORTD3D
5600                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5601                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5602 #endif
5603                         break;
5604                 case RENDERPATH_D3D10:
5605                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5606                         break;
5607                 case RENDERPATH_D3D11:
5608                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5609                         break;
5610                 case RENDERPATH_GL11:
5611                 case RENDERPATH_GL13:
5612                 case RENDERPATH_GLES1:
5613 #ifndef USE_GLES2
5614                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5615 #endif
5616                         break;
5617                 case RENDERPATH_SOFT:
5618                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5619                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5620                         break;
5621                 case RENDERPATH_GL20:
5622                 case RENDERPATH_GLES2:
5623                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5624                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5625                         break;
5626                 }
5627         }
5628 }
5629
5630 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5631 {
5632         r_viewport_t viewport;
5633
5634         CHECKGLERROR
5635
5636         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5637         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5638         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5639         R_SetViewport(&viewport);
5640         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5641         GL_Color(1, 1, 1, 1);
5642         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5643         GL_BlendFunc(GL_ONE, GL_ZERO);
5644         GL_ScissorTest(false);
5645         GL_DepthMask(false);
5646         GL_DepthRange(0, 1);
5647         GL_DepthTest(false);
5648         GL_DepthFunc(GL_LEQUAL);
5649         R_EntityMatrix(&identitymatrix);
5650         R_Mesh_ResetTextureState();
5651         GL_PolygonOffset(0, 0);
5652         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5653         switch(vid.renderpath)
5654         {
5655         case RENDERPATH_GL11:
5656         case RENDERPATH_GL13:
5657         case RENDERPATH_GL20:
5658         case RENDERPATH_GLES1:
5659         case RENDERPATH_GLES2:
5660                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5661                 break;
5662         case RENDERPATH_D3D9:
5663         case RENDERPATH_D3D10:
5664         case RENDERPATH_D3D11:
5665         case RENDERPATH_SOFT:
5666                 break;
5667         }
5668         GL_CullFace(GL_NONE);
5669
5670         CHECKGLERROR
5671 }
5672
5673 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5674 {
5675         DrawQ_Finish();
5676
5677         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5678 }
5679
5680 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5681 {
5682         DrawQ_Finish();
5683
5684         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5685         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5686         GL_Color(1, 1, 1, 1);
5687         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5688         GL_BlendFunc(GL_ONE, GL_ZERO);
5689         GL_ScissorTest(true);
5690         GL_DepthMask(true);
5691         GL_DepthRange(0, 1);
5692         GL_DepthTest(true);
5693         GL_DepthFunc(GL_LEQUAL);
5694         R_EntityMatrix(&identitymatrix);
5695         R_Mesh_ResetTextureState();
5696         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5697         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5698         switch(vid.renderpath)
5699         {
5700         case RENDERPATH_GL11:
5701         case RENDERPATH_GL13:
5702         case RENDERPATH_GL20:
5703         case RENDERPATH_GLES1:
5704         case RENDERPATH_GLES2:
5705                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5706                 break;
5707         case RENDERPATH_D3D9:
5708         case RENDERPATH_D3D10:
5709         case RENDERPATH_D3D11:
5710         case RENDERPATH_SOFT:
5711                 break;
5712         }
5713         GL_CullFace(r_refdef.view.cullface_back);
5714 }
5715
5716 /*
5717 ================
5718 R_RenderView_UpdateViewVectors
5719 ================
5720 */
5721 void R_RenderView_UpdateViewVectors(void)
5722 {
5723         // break apart the view matrix into vectors for various purposes
5724         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5725         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5726         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5727         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5728         // make an inverted copy of the view matrix for tracking sprites
5729         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5730 }
5731
5732 void R_RenderTarget_FreeUnused(qboolean force)
5733 {
5734         int i, j, end;
5735         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5736         for (i = 0; i < end; i++)
5737         {
5738                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5739                 // free resources for rendertargets that have not been used for a while
5740                 // (note: this check is run after the frame render, so any targets used
5741                 // this frame will not be affected even at low framerates)
5742                 if (r && (realtime - r->lastusetime > 0.2 || force))
5743                 {
5744                         if (r->fbo)
5745                                 R_Mesh_DestroyFramebufferObject(r->fbo);
5746                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5747                                 if (r->colortexture[j])
5748                                         R_FreeTexture(r->colortexture[j]);
5749                         if (r->depthtexture)
5750                                 R_FreeTexture(r->depthtexture);
5751                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5752                 }
5753         }
5754 }
5755
5756 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5757 {
5758         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5759         switch (vid.renderpath)
5760         {
5761         case RENDERPATH_D3D9:
5762                 x1 = (x + 0.5f) * iw;
5763                 x2 = (x + 0.5f + w) * iw;
5764                 y1 = (y + 0.5f) * ih;
5765                 y2 = (y + 0.5f + h) * ih;
5766                 break;
5767         default:
5768                 x1 = x * iw;
5769                 x2 = (x + w) * iw;
5770                 y1 = (th - y) * ih;
5771                 y2 = (th - y - h) * ih;
5772                 break;
5773         }
5774         texcoord2f[0] = x1;
5775         texcoord2f[2] = x2;
5776         texcoord2f[4] = x2;
5777         texcoord2f[6] = x1;
5778         texcoord2f[1] = y1;
5779         texcoord2f[3] = y1;
5780         texcoord2f[5] = y2;
5781         texcoord2f[7] = y2;
5782 }
5783
5784 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5785 {
5786         int i, j, end;
5787         r_rendertarget_t *r = NULL;
5788         char vabuf[256];
5789         // first try to reuse an existing slot if possible
5790         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5791         for (i = 0; i < end; i++)
5792         {
5793                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5794                 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5795                         break;
5796         }
5797         if (i == end)
5798         {
5799                 // no unused exact match found, so we have to make one in the first unused slot
5800                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5801                 r->texturewidth = texturewidth;
5802                 r->textureheight = textureheight;
5803                 r->colortextype[0] = colortextype0;
5804                 r->colortextype[1] = colortextype1;
5805                 r->colortextype[2] = colortextype2;
5806                 r->colortextype[3] = colortextype3;
5807                 r->depthtextype = depthtextype;
5808                 r->depthisrenderbuffer = depthisrenderbuffer;
5809                 for (j = 0; j < 4; j++)
5810                         if (r->colortextype[j])
5811                                 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5812                 if (r->depthtextype)
5813                 {
5814                         if (r->depthisrenderbuffer)
5815                                 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5816                         else
5817                                 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5818                 }
5819                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5820         }
5821         r_refdef.stats[r_stat_rendertargets_used]++;
5822         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5823         r->lastusetime = realtime;
5824         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5825         return r;
5826 }
5827
5828 static void R_Water_StartFrame(void)
5829 {
5830         int waterwidth, waterheight;
5831
5832         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5833                 return;
5834
5835         switch(vid.renderpath)
5836         {
5837         case RENDERPATH_GL20:
5838         case RENDERPATH_D3D9:
5839         case RENDERPATH_D3D10:
5840         case RENDERPATH_D3D11:
5841         case RENDERPATH_SOFT:
5842         case RENDERPATH_GLES2:
5843                 break;
5844         case RENDERPATH_GL11:
5845         case RENDERPATH_GL13:
5846         case RENDERPATH_GLES1:
5847                 return;
5848         }
5849
5850         // set waterwidth and waterheight to the water resolution that will be
5851         // used (often less than the screen resolution for faster rendering)
5852         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5853         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5854         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5855
5856         if (!r_water.integer || r_showsurfaces.integer)
5857                 waterwidth = waterheight = 0;
5858
5859         // set up variables that will be used in shader setup
5860         r_fb.water.waterwidth = waterwidth;
5861         r_fb.water.waterheight = waterheight;
5862         r_fb.water.texturewidth = waterwidth;
5863         r_fb.water.textureheight = waterheight;
5864         r_fb.water.camerawidth = waterwidth;
5865         r_fb.water.cameraheight = waterheight;
5866         r_fb.water.screenscale[0] = 0.5f;
5867         r_fb.water.screenscale[1] = 0.5f;
5868         r_fb.water.screencenter[0] = 0.5f;
5869         r_fb.water.screencenter[1] = 0.5f;
5870         r_fb.water.enabled = waterwidth != 0;
5871
5872         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5873         r_fb.water.numwaterplanes = 0;
5874 }
5875
5876 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5877 {
5878         int planeindex, bestplaneindex, vertexindex;
5879         vec3_t mins, maxs, normal, center, v, n;
5880         vec_t planescore, bestplanescore;
5881         mplane_t plane;
5882         r_waterstate_waterplane_t *p;
5883         texture_t *t = R_GetCurrentTexture(surface->texture);
5884
5885         rsurface.texture = t;
5886         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5887         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5888         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5889                 return;
5890         // average the vertex normals, find the surface bounds (after deformvertexes)
5891         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5892         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5893         VectorCopy(n, normal);
5894         VectorCopy(v, mins);
5895         VectorCopy(v, maxs);
5896         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5897         {
5898                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5899                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5900                 VectorAdd(normal, n, normal);
5901                 mins[0] = min(mins[0], v[0]);
5902                 mins[1] = min(mins[1], v[1]);
5903                 mins[2] = min(mins[2], v[2]);
5904                 maxs[0] = max(maxs[0], v[0]);
5905                 maxs[1] = max(maxs[1], v[1]);
5906                 maxs[2] = max(maxs[2], v[2]);
5907         }
5908         VectorNormalize(normal);
5909         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5910
5911         VectorCopy(normal, plane.normal);
5912         VectorNormalize(plane.normal);
5913         plane.dist = DotProduct(center, plane.normal);
5914         PlaneClassify(&plane);
5915         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5916         {
5917                 // skip backfaces (except if nocullface is set)
5918 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5919 //                      return;
5920                 VectorNegate(plane.normal, plane.normal);
5921                 plane.dist *= -1;
5922                 PlaneClassify(&plane);
5923         }
5924
5925
5926         // find a matching plane if there is one
5927         bestplaneindex = -1;
5928         bestplanescore = 1048576.0f;
5929         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5930         {
5931                 if(p->camera_entity == t->camera_entity)
5932                 {
5933                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5934                         if (bestplaneindex < 0 || bestplanescore > planescore)
5935                         {
5936                                 bestplaneindex = planeindex;
5937                                 bestplanescore = planescore;
5938                         }
5939                 }
5940         }
5941         planeindex = bestplaneindex;
5942
5943         // if this surface does not fit any known plane rendered this frame, add one
5944         if (planeindex < 0 || bestplanescore > 0.001f)
5945         {
5946                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5947                 {
5948                         // store the new plane
5949                         planeindex = r_fb.water.numwaterplanes++;
5950                         p = r_fb.water.waterplanes + planeindex;
5951                         p->plane = plane;
5952                         // clear materialflags and pvs
5953                         p->materialflags = 0;
5954                         p->pvsvalid = false;
5955                         p->camera_entity = t->camera_entity;
5956                         VectorCopy(mins, p->mins);
5957                         VectorCopy(maxs, p->maxs);
5958                 }
5959                 else
5960                 {
5961                         // We're totally screwed.
5962                         return;
5963                 }
5964         }
5965         else
5966         {
5967                 // merge mins/maxs when we're adding this surface to the plane
5968                 p = r_fb.water.waterplanes + planeindex;
5969                 p->mins[0] = min(p->mins[0], mins[0]);
5970                 p->mins[1] = min(p->mins[1], mins[1]);
5971                 p->mins[2] = min(p->mins[2], mins[2]);
5972                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5973                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5974                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5975         }
5976         // merge this surface's materialflags into the waterplane
5977         p->materialflags |= t->currentmaterialflags;
5978         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5979         {
5980                 // merge this surface's PVS into the waterplane
5981                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5982                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5983                 {
5984                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5985                         p->pvsvalid = true;
5986                 }
5987         }
5988 }
5989
5990 extern cvar_t r_drawparticles;
5991 extern cvar_t r_drawdecals;
5992
5993 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
5994 {
5995         int myscissor[4];
5996         r_refdef_view_t originalview;
5997         r_refdef_view_t myview;
5998         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;
5999         r_waterstate_waterplane_t *p;
6000         vec3_t visorigin;
6001         r_rendertarget_t *rt;
6002
6003         originalview = r_refdef.view;
6004
6005         // lowquality hack, temporarily shut down some cvars and restore afterwards
6006         qualityreduction = r_water_lowquality.integer;
6007         if (qualityreduction > 0)
6008         {
6009                 if (qualityreduction >= 1)
6010                 {
6011                         old_r_shadows = r_shadows.integer;
6012                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6013                         old_r_dlight = r_shadow_realtime_dlight.integer;
6014                         Cvar_SetValueQuick(&r_shadows, 0);
6015                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6016                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6017                 }
6018                 if (qualityreduction >= 2)
6019                 {
6020                         old_r_dynamic = r_dynamic.integer;
6021                         old_r_particles = r_drawparticles.integer;
6022                         old_r_decals = r_drawdecals.integer;
6023                         Cvar_SetValueQuick(&r_dynamic, 0);
6024                         Cvar_SetValueQuick(&r_drawparticles, 0);
6025                         Cvar_SetValueQuick(&r_drawdecals, 0);
6026                 }
6027         }
6028
6029         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6030         {
6031                 p->rt_reflection = NULL;
6032                 p->rt_refraction = NULL;
6033                 p->rt_camera = NULL;
6034         }
6035
6036         // render views
6037         r_refdef.view = originalview;
6038         r_refdef.view.showdebug = false;
6039         r_refdef.view.width = r_fb.water.waterwidth;
6040         r_refdef.view.height = r_fb.water.waterheight;
6041         r_refdef.view.useclipplane = true;
6042         myview = r_refdef.view;
6043         r_fb.water.renderingscene = true;
6044         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6045         {
6046                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6047                         continue;
6048
6049                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6050                 {
6051                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6052                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6053                                 goto error;
6054                         r_refdef.view = myview;
6055                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6056                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6057                         if(r_water_scissormode.integer)
6058                         {
6059                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6060                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6061                                 {
6062                                         p->rt_reflection = NULL;
6063                                         p->rt_refraction = NULL;
6064                                         p->rt_camera = NULL;
6065                                         continue;
6066                                 }
6067                         }
6068
6069                         r_refdef.view.clipplane = p->plane;
6070                         // reverse the cullface settings for this render
6071                         r_refdef.view.cullface_front = GL_FRONT;
6072                         r_refdef.view.cullface_back = GL_BACK;
6073                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6074                         {
6075                                 r_refdef.view.usecustompvs = true;
6076                                 if (p->pvsvalid)
6077                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6078                                 else
6079                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6080                         }
6081
6082                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6083                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6084                         GL_ScissorTest(false);
6085                         R_ClearScreen(r_refdef.fogenabled);
6086                         GL_ScissorTest(true);
6087                         if(r_water_scissormode.integer & 2)
6088                                 R_View_UpdateWithScissor(myscissor);
6089                         else
6090                                 R_View_Update();
6091                         R_AnimCache_CacheVisibleEntities();
6092                         if(r_water_scissormode.integer & 1)
6093                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6094                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6095
6096                         r_fb.water.hideplayer = false;
6097                         p->rt_reflection = rt;
6098                 }
6099
6100                 // render the normal view scene and copy into texture
6101                 // (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)
6102                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6103                 {
6104                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6105                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6106                                 goto error;
6107                         r_refdef.view = myview;
6108                         if(r_water_scissormode.integer)
6109                         {
6110                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6111                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6112                                 {
6113                                         p->rt_reflection = NULL;
6114                                         p->rt_refraction = NULL;
6115                                         p->rt_camera = NULL;
6116                                         continue;
6117                                 }
6118                         }
6119
6120                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6121
6122                         r_refdef.view.clipplane = p->plane;
6123                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6124                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6125
6126                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6127                         {
6128                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6129                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6130                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6131                                 R_RenderView_UpdateViewVectors();
6132                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6133                                 {
6134                                         r_refdef.view.usecustompvs = true;
6135                                         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);
6136                                 }
6137                         }
6138
6139                         PlaneClassify(&r_refdef.view.clipplane);
6140
6141                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6142                         GL_ScissorTest(false);
6143                         R_ClearScreen(r_refdef.fogenabled);
6144                         GL_ScissorTest(true);
6145                         if(r_water_scissormode.integer & 2)
6146                                 R_View_UpdateWithScissor(myscissor);
6147                         else
6148                                 R_View_Update();
6149                         R_AnimCache_CacheVisibleEntities();
6150                         if(r_water_scissormode.integer & 1)
6151                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6152                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6153
6154                         r_fb.water.hideplayer = false;
6155                         p->rt_refraction = rt;
6156                 }
6157                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6158                 {
6159                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6160                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6161                                 goto error;
6162                         r_refdef.view = myview;
6163
6164                         r_refdef.view.clipplane = p->plane;
6165                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6166                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6167
6168                         r_refdef.view.width = r_fb.water.camerawidth;
6169                         r_refdef.view.height = r_fb.water.cameraheight;
6170                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6171                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6172                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6173                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6174
6175                         if(p->camera_entity)
6176                         {
6177                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6178                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6179                         }
6180
6181                         // note: all of the view is used for displaying... so
6182                         // there is no use in scissoring
6183
6184                         // reverse the cullface settings for this render
6185                         r_refdef.view.cullface_front = GL_FRONT;
6186                         r_refdef.view.cullface_back = GL_BACK;
6187                         // also reverse the view matrix
6188                         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
6189                         R_RenderView_UpdateViewVectors();
6190                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6191                         {
6192                                 r_refdef.view.usecustompvs = true;
6193                                 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);
6194                         }
6195                         
6196                         // camera needs no clipplane
6197                         r_refdef.view.useclipplane = false;
6198
6199                         PlaneClassify(&r_refdef.view.clipplane);
6200
6201                         r_fb.water.hideplayer = false;
6202
6203                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6204                         GL_ScissorTest(false);
6205                         R_ClearScreen(r_refdef.fogenabled);
6206                         GL_ScissorTest(true);
6207                         R_View_Update();
6208                         R_AnimCache_CacheVisibleEntities();
6209                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6210
6211                         r_fb.water.hideplayer = false;
6212                         p->rt_camera = rt;
6213                 }
6214
6215         }
6216         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6217         r_fb.water.renderingscene = false;
6218         r_refdef.view = originalview;
6219         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6220         R_View_Update();
6221         R_AnimCache_CacheVisibleEntities();
6222         goto finish;
6223 error:
6224         r_refdef.view = originalview;
6225         r_fb.water.renderingscene = false;
6226         Cvar_SetValueQuick(&r_water, 0);
6227         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6228 finish:
6229         // lowquality hack, restore cvars
6230         if (qualityreduction > 0)
6231         {
6232                 if (qualityreduction >= 1)
6233                 {
6234                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6235                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6236                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6237                 }
6238                 if (qualityreduction >= 2)
6239                 {
6240                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6241                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6242                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6243                 }
6244         }
6245 }
6246
6247 static void R_Bloom_StartFrame(void)
6248 {
6249         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6250         int viewwidth, viewheight;
6251         textype_t textype = TEXTYPE_COLORBUFFER;
6252
6253         // clear the pointers to rendertargets from last frame as they're stale
6254         r_fb.rt_screen = NULL;
6255         r_fb.rt_bloom = NULL;
6256
6257         switch (vid.renderpath)
6258         {
6259         case RENDERPATH_GL20:
6260                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6261                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6262                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6263                 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6264                 if (!vid.support.ext_framebuffer_object)
6265                         return;
6266                 break;
6267         case RENDERPATH_GL11:
6268         case RENDERPATH_GL13:
6269         case RENDERPATH_GLES1:
6270                 return; // don't bother
6271         case RENDERPATH_GLES2:
6272         case RENDERPATH_D3D9:
6273         case RENDERPATH_D3D10:
6274         case RENDERPATH_D3D11:
6275                 r_fb.usedepthtextures = false;
6276                 break;
6277         case RENDERPATH_SOFT:
6278                 r_fb.usedepthtextures = true;
6279                 break;
6280         }
6281
6282         if (r_viewscale_fpsscaling.integer)
6283         {
6284                 double actualframetime;
6285                 double targetframetime;
6286                 double adjust;
6287                 actualframetime = r_refdef.lastdrawscreentime;
6288                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6289                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6290                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6291                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6292                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6293                 viewscalefpsadjusted += adjust;
6294                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6295         }
6296         else
6297                 viewscalefpsadjusted = 1.0f;
6298
6299         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6300
6301         // set bloomwidth and bloomheight to the bloom resolution that will be
6302         // used (often less than the screen resolution for faster rendering)
6303         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6304         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6305         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6306         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6307         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6308
6309         // calculate desired texture sizes
6310         screentexturewidth = viewwidth;
6311         screentextureheight = viewheight;
6312         bloomtexturewidth = r_fb.bloomwidth;
6313         bloomtextureheight = r_fb.bloomheight;
6314
6315         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))
6316         {
6317                 Cvar_SetValueQuick(&r_bloom, 0);
6318                 Cvar_SetValueQuick(&r_motionblur, 0);
6319                 Cvar_SetValueQuick(&r_damageblur, 0);
6320         }
6321
6322         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6323         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6324         {
6325                 if (r_fb.ghosttexture)
6326                         R_FreeTexture(r_fb.ghosttexture);
6327                 r_fb.ghosttexture = NULL;
6328
6329                 r_fb.screentexturewidth = screentexturewidth;
6330                 r_fb.screentextureheight = screentextureheight;
6331                 r_fb.textype = textype;
6332
6333                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6334                 {
6335                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6336                                 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);
6337                         r_fb.ghosttexture_valid = false;
6338                 }
6339         }
6340
6341         if (r_bloom.integer)
6342         {
6343                 // bloom texture is a different resolution
6344                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6345                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6346                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6347         }
6348         else
6349                 r_fb.bloomwidth = r_fb.bloomheight = 0;
6350
6351         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6352
6353         r_refdef.view.clear = true;
6354 }
6355
6356 static void R_Bloom_MakeTexture(void)
6357 {
6358         int x, range, dir;
6359         float xoffset, yoffset, r, brighten;
6360         float colorscale = r_bloom_colorscale.value;
6361         r_viewport_t bloomviewport;
6362         r_rendertarget_t *prev, *cur;
6363         textype_t textype = r_fb.rt_screen->colortextype[0];
6364
6365         r_refdef.stats[r_stat_bloom]++;
6366
6367         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6368
6369         // scale down screen texture to the bloom texture size
6370         CHECKGLERROR
6371         prev = r_fb.rt_screen;
6372         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6373         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6374         R_SetViewport(&bloomviewport);
6375         GL_CullFace(GL_NONE);
6376         GL_DepthTest(false);
6377         GL_BlendFunc(GL_ONE, GL_ZERO);
6378         GL_Color(colorscale, colorscale, colorscale, 1);
6379         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6380         // TODO: do boxfilter scale-down in shader?
6381         R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6382         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6383         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6384         // we now have a properly scaled bloom image
6385
6386         // multiply bloom image by itself as many times as desired to darken it
6387         // TODO: if people actually use this it could be done more quickly in the previous shader pass
6388         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6389         {
6390                 prev = cur;
6391                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6392                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6393                 x *= 2;
6394                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6395                 if(x <= 2)
6396                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6397                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6398                 GL_Color(1,1,1,1); // no fix factor supported here
6399                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6400                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6401                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6402                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6403         }
6404
6405         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6406         brighten = r_bloom_brighten.value;
6407         brighten = sqrt(brighten);
6408         if(range >= 1)
6409                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6410
6411         for (dir = 0;dir < 2;dir++)
6412         {
6413                 prev = cur;
6414                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6415                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6416                 // blend on at multiple vertical offsets to achieve a vertical blur
6417                 // TODO: do offset blends using GLSL
6418                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6419                 GL_BlendFunc(GL_ONE, GL_ZERO);
6420                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6421                 for (x = -range;x <= range;x++)
6422                 {
6423                         if (!dir){xoffset = 0;yoffset = x;}
6424                         else {xoffset = x;yoffset = 0;}
6425                         xoffset /= (float)prev->texturewidth;
6426                         yoffset /= (float)prev->textureheight;
6427                         // compute a texcoord array with the specified x and y offset
6428                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6429                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6430                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6431                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6432                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6433                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6434                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6435                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6436                         // this r value looks like a 'dot' particle, fading sharply to
6437                         // black at the edges
6438                         // (probably not realistic but looks good enough)
6439                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6440                         //r = brighten/(range*2+1);
6441                         r = brighten / (range * 2 + 1);
6442                         if(range >= 1)
6443                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
6444                         if (r <= 0)
6445                                 continue;
6446                         GL_Color(r, r, r, 1);
6447                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6448                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6449                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6450                         GL_BlendFunc(GL_ONE, GL_ONE);
6451                 }
6452         }
6453
6454         // now we have the bloom image, so keep track of it
6455         r_fb.rt_bloom = cur;
6456 }
6457
6458 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6459 {
6460         dpuint64 permutation;
6461         float uservecs[4][4];
6462         rtexture_t *viewtexture;
6463         rtexture_t *bloomtexture;
6464
6465         R_EntityMatrix(&identitymatrix);
6466
6467         switch (vid.renderpath)
6468         {
6469         case RENDERPATH_GL20:
6470         case RENDERPATH_D3D9:
6471         case RENDERPATH_D3D10:
6472         case RENDERPATH_D3D11:
6473         case RENDERPATH_SOFT:
6474         case RENDERPATH_GLES2:
6475                 permutation =
6476                           (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6477                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6478                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6479                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6480                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6481
6482                 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6483                 {
6484                         // declare variables
6485                         float blur_factor, blur_mouseaccel, blur_velocity;
6486                         static float blur_average; 
6487                         static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6488
6489                         // set a goal for the factoring
6490                         blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6491                                 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6492                         blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6493                                 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6494                         blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6495                                 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6496
6497                         // from the goal, pick an averaged value between goal and last value
6498                         cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6499                         blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6500
6501                         // enforce minimum amount of blur 
6502                         blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6503
6504                         //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6505
6506                         // calculate values into a standard alpha
6507                         cl.motionbluralpha = 1 - exp(-
6508                                         (
6509                                                 (r_motionblur.value * blur_factor / 80)
6510                                                 +
6511                                                 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6512                                         )
6513                                         /
6514                                         max(0.0001, cl.time - cl.oldtime) // fps independent
6515                                         );
6516
6517                         // randomization for the blur value to combat persistent ghosting
6518                         cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6519                         cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6520
6521                         // apply the blur
6522                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6523                         if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6524                         {
6525                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6526                                 GL_Color(1, 1, 1, cl.motionbluralpha);
6527                                 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6528                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6529                                 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6530                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6531                                 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6532                         }
6533
6534                         // updates old view angles for next pass
6535                         VectorCopy(cl.viewangles, blur_oldangles);
6536
6537                         // copy view into the ghost texture
6538                         R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6539                         r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6540                         r_fb.ghosttexture_valid = true;
6541                 }
6542
6543                 if (r_fb.bloomwidth)
6544                 {
6545                         // make the bloom texture
6546                         R_Bloom_MakeTexture();
6547                 }
6548
6549 #if _MSC_VER >= 1400
6550 #define sscanf sscanf_s
6551 #endif
6552                 memset(uservecs, 0, sizeof(uservecs));
6553                 if (r_glsl_postprocess_uservec1_enable.integer)
6554                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6555                 if (r_glsl_postprocess_uservec2_enable.integer)
6556                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6557                 if (r_glsl_postprocess_uservec3_enable.integer)
6558                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6559                 if (r_glsl_postprocess_uservec4_enable.integer)
6560                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6561
6562                 // render to the screen fbo
6563                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6564                 GL_Color(1, 1, 1, 1);
6565                 GL_BlendFunc(GL_ONE, GL_ZERO);
6566
6567                 viewtexture = r_fb.rt_screen->colortexture[0];
6568                 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6569
6570                 if (r_rendertarget_debug.integer >= 0)
6571                 {
6572                         r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6573                         if (rt && rt->colortexture[0])
6574                         {
6575                                 viewtexture = rt->colortexture[0];
6576                                 bloomtexture = NULL;
6577                         }
6578                 }
6579
6580                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6581                 switch(vid.renderpath)
6582                 {
6583                 case RENDERPATH_GL20:
6584                 case RENDERPATH_GLES2:
6585                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6586                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
6587                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
6588                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6589                         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]);
6590                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6591                         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]);
6592                         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]);
6593                         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]);
6594                         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]);
6595                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6596                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6597                         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);
6598                         break;
6599                 case RENDERPATH_D3D9:
6600 #ifdef SUPPORTD3D
6601                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6602                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6603                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6604                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6605                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6606                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6607                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6608                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6609                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6610                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6611                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6612                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6613                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6614 #endif
6615                         break;
6616                 case RENDERPATH_D3D10:
6617                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6618                         break;
6619                 case RENDERPATH_D3D11:
6620                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6621                         break;
6622                 case RENDERPATH_SOFT:
6623                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6624                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6625                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6626                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6627                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6628                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6629                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6630                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6631                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6632                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6633                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6634                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6635                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6636                         break;
6637                 default:
6638                         break;
6639                 }
6640                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6641                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6642                 break;
6643         case RENDERPATH_GL11:
6644         case RENDERPATH_GL13:
6645         case RENDERPATH_GLES1:
6646                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6647                 {
6648                         // apply a color tint to the whole view
6649                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6650                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6651                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6652                         R_SetupShader_Generic_NoTexture(false, true);
6653                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6654                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6655                 }
6656                 break;
6657         }
6658 }
6659
6660 matrix4x4_t r_waterscrollmatrix;
6661
6662 void R_UpdateFog(void)
6663 {
6664         // Nehahra fog
6665         if (gamemode == GAME_NEHAHRA)
6666         {
6667                 if (gl_fogenable.integer)
6668                 {
6669                         r_refdef.oldgl_fogenable = true;
6670                         r_refdef.fog_density = gl_fogdensity.value;
6671                         r_refdef.fog_red = gl_fogred.value;
6672                         r_refdef.fog_green = gl_foggreen.value;
6673                         r_refdef.fog_blue = gl_fogblue.value;
6674                         r_refdef.fog_alpha = 1;
6675                         r_refdef.fog_start = 0;
6676                         r_refdef.fog_end = gl_skyclip.value;
6677                         r_refdef.fog_height = 1<<30;
6678                         r_refdef.fog_fadedepth = 128;
6679                 }
6680                 else if (r_refdef.oldgl_fogenable)
6681                 {
6682                         r_refdef.oldgl_fogenable = false;
6683                         r_refdef.fog_density = 0;
6684                         r_refdef.fog_red = 0;
6685                         r_refdef.fog_green = 0;
6686                         r_refdef.fog_blue = 0;
6687                         r_refdef.fog_alpha = 0;
6688                         r_refdef.fog_start = 0;
6689                         r_refdef.fog_end = 0;
6690                         r_refdef.fog_height = 1<<30;
6691                         r_refdef.fog_fadedepth = 128;
6692                 }
6693         }
6694
6695         // fog parms
6696         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6697         r_refdef.fog_start = max(0, r_refdef.fog_start);
6698         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6699
6700         if (r_refdef.fog_density && r_drawfog.integer)
6701         {
6702                 r_refdef.fogenabled = true;
6703                 // this is the point where the fog reaches 0.9986 alpha, which we
6704                 // consider a good enough cutoff point for the texture
6705                 // (0.9986 * 256 == 255.6)
6706                 if (r_fog_exp2.integer)
6707                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6708                 else
6709                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6710                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6711                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6712                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6713                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6714                         R_BuildFogHeightTexture();
6715                 // fog color was already set
6716                 // update the fog texture
6717                 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)
6718                         R_BuildFogTexture();
6719                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6720                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6721         }
6722         else
6723                 r_refdef.fogenabled = false;
6724
6725         // fog color
6726         if (r_refdef.fog_density)
6727         {
6728                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6729                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6730                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6731
6732                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6733                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6734                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6735                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6736
6737                 {
6738                         vec3_t fogvec;
6739                         VectorCopy(r_refdef.fogcolor, fogvec);
6740                         //   color.rgb *= ContrastBoost * SceneBrightness;
6741                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6742                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6743                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6744                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6745                 }
6746         }
6747 }
6748
6749 void R_UpdateVariables(void)
6750 {
6751         R_Textures_Frame();
6752
6753         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6754
6755         r_refdef.farclip = r_farclip_base.value;
6756         if (r_refdef.scene.worldmodel)
6757                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6758         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6759
6760         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6761                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6762         r_refdef.polygonfactor = 0;
6763         r_refdef.polygonoffset = 0;
6764         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6765         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6766
6767         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6768         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6769         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6770         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6771         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6772         if (FAKELIGHT_ENABLED)
6773         {
6774                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6775         }
6776         else if (r_refdef.scene.worldmodel)
6777         {
6778                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6779         }
6780         if (r_showsurfaces.integer)
6781         {
6782                 r_refdef.scene.rtworld = false;
6783                 r_refdef.scene.rtworldshadows = false;
6784                 r_refdef.scene.rtdlight = false;
6785                 r_refdef.scene.rtdlightshadows = false;
6786                 r_refdef.scene.lightmapintensity = 0;
6787         }
6788
6789         r_gpuskeletal = false;
6790         switch(vid.renderpath)
6791         {
6792         case RENDERPATH_GL20:
6793                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6794         case RENDERPATH_D3D9:
6795         case RENDERPATH_D3D10:
6796         case RENDERPATH_D3D11:
6797         case RENDERPATH_SOFT:
6798         case RENDERPATH_GLES2:
6799                 if(!vid_gammatables_trivial)
6800                 {
6801                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6802                         {
6803                                 // build GLSL gamma texture
6804 #define RAMPWIDTH 256
6805                                 unsigned short ramp[RAMPWIDTH * 3];
6806                                 unsigned char rampbgr[RAMPWIDTH][4];
6807                                 int i;
6808
6809                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6810
6811                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6812                                 for(i = 0; i < RAMPWIDTH; ++i)
6813                                 {
6814                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6815                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6816                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6817                                         rampbgr[i][3] = 0;
6818                                 }
6819                                 if (r_texture_gammaramps)
6820                                 {
6821                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6822                                 }
6823                                 else
6824                                 {
6825                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6826                                 }
6827                         }
6828                 }
6829                 else
6830                 {
6831                         // remove GLSL gamma texture
6832                 }
6833                 break;
6834         case RENDERPATH_GL11:
6835         case RENDERPATH_GL13:
6836         case RENDERPATH_GLES1:
6837                 break;
6838         }
6839 }
6840
6841 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6842 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6843 /*
6844 ================
6845 R_SelectScene
6846 ================
6847 */
6848 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6849         if( scenetype != r_currentscenetype ) {
6850                 // store the old scenetype
6851                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6852                 r_currentscenetype = scenetype;
6853                 // move in the new scene
6854                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6855         }
6856 }
6857
6858 /*
6859 ================
6860 R_GetScenePointer
6861 ================
6862 */
6863 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6864 {
6865         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6866         if( scenetype == r_currentscenetype ) {
6867                 return &r_refdef.scene;
6868         } else {
6869                 return &r_scenes_store[ scenetype ];
6870         }
6871 }
6872
6873 static int R_SortEntities_Compare(const void *ap, const void *bp)
6874 {
6875         const entity_render_t *a = *(const entity_render_t **)ap;
6876         const entity_render_t *b = *(const entity_render_t **)bp;
6877
6878         // 1. compare model
6879         if(a->model < b->model)
6880                 return -1;
6881         if(a->model > b->model)
6882                 return +1;
6883
6884         // 2. compare skin
6885         // TODO possibly calculate the REAL skinnum here first using
6886         // skinscenes?
6887         if(a->skinnum < b->skinnum)
6888                 return -1;
6889         if(a->skinnum > b->skinnum)
6890                 return +1;
6891
6892         // everything we compared is equal
6893         return 0;
6894 }
6895 static void R_SortEntities(void)
6896 {
6897         // below or equal 2 ents, sorting never gains anything
6898         if(r_refdef.scene.numentities <= 2)
6899                 return;
6900         // sort
6901         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6902 }
6903
6904 /*
6905 ================
6906 R_RenderView
6907 ================
6908 */
6909 int dpsoftrast_test;
6910 extern cvar_t r_shadow_bouncegrid;
6911 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6912 {
6913         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6914         int viewfbo = 0;
6915         rtexture_t *viewdepthtexture = NULL;
6916         rtexture_t *viewcolortexture = NULL;
6917         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6918
6919         dpsoftrast_test = r_test.integer;
6920
6921         if (r_timereport_active)
6922                 R_TimeReport("start");
6923         r_textureframe++; // used only by R_GetCurrentTexture
6924         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6925
6926         if(R_CompileShader_CheckStaticParms())
6927                 R_GLSL_Restart_f();
6928
6929         if (!r_drawentities.integer)
6930                 r_refdef.scene.numentities = 0;
6931         else if (r_sortentities.integer)
6932                 R_SortEntities();
6933
6934         R_AnimCache_ClearCache();
6935
6936         /* adjust for stereo display */
6937         if(R_Stereo_Active())
6938         {
6939                 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);
6940                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6941         }
6942
6943         if (r_refdef.view.isoverlay)
6944         {
6945                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6946                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6947                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6948                 R_TimeReport("depthclear");
6949
6950                 r_refdef.view.showdebug = false;
6951
6952                 r_fb.water.enabled = false;
6953                 r_fb.water.numwaterplanes = 0;
6954
6955                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6956
6957                 r_refdef.view.matrix = originalmatrix;
6958
6959                 CHECKGLERROR
6960                 return;
6961         }
6962
6963         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6964         {
6965                 r_refdef.view.matrix = originalmatrix;
6966                 return;
6967         }
6968
6969         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6970
6971         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6972                 // in sRGB fallback, behave similar to true sRGB: convert this
6973                 // value from linear to sRGB
6974                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6975
6976         R_RenderView_UpdateViewVectors();
6977
6978         R_Shadow_UpdateWorldLightSelection();
6979
6980         // this will set up r_fb.rt_screen
6981         R_Bloom_StartFrame();
6982
6983         // apply bloom brightness offset
6984         if(r_fb.rt_bloom)
6985                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6986
6987         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
6988         if (r_fb.rt_screen)
6989         {
6990                 viewfbo = r_fb.rt_screen->fbo;
6991                 viewdepthtexture = r_fb.rt_screen->depthtexture;
6992                 viewcolortexture = r_fb.rt_screen->colortexture[0];
6993                 viewx = 0;
6994                 viewy = 0;
6995                 viewwidth = width;
6996                 viewheight = height;
6997         }
6998
6999         R_Water_StartFrame();
7000
7001         CHECKGLERROR
7002         if (r_timereport_active)
7003                 R_TimeReport("viewsetup");
7004
7005         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7006
7007         // clear the whole fbo every frame - otherwise the driver will consider
7008         // it to be an inter-frame texture and stall in multi-gpu configurations
7009         if (r_fb.rt_screen)
7010                 GL_ScissorTest(false);
7011         R_ClearScreen(r_refdef.fogenabled);
7012         if (r_timereport_active)
7013                 R_TimeReport("viewclear");
7014
7015         r_refdef.view.clear = true;
7016
7017         r_refdef.view.showdebug = true;
7018
7019         R_View_Update();
7020         if (r_timereport_active)
7021                 R_TimeReport("visibility");
7022
7023         R_AnimCache_CacheVisibleEntities();
7024         if (r_timereport_active)
7025                 R_TimeReport("animcache");
7026
7027         R_Shadow_UpdateBounceGridTexture();
7028         if (r_timereport_active && r_shadow_bouncegrid.integer)
7029                 R_TimeReport("bouncegrid");
7030
7031         r_fb.water.numwaterplanes = 0;
7032         if (r_fb.water.enabled)
7033                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7034
7035         // for the actual view render we use scissoring a fair amount, so scissor
7036         // test needs to be on
7037         if (r_fb.rt_screen)
7038                 GL_ScissorTest(true);
7039         GL_Scissor(viewx, viewy, viewwidth, viewheight);
7040         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7041         r_fb.water.numwaterplanes = 0;
7042
7043         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7044         GL_ScissorTest(false);
7045
7046         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7047         if (r_timereport_active)
7048                 R_TimeReport("blendview");
7049
7050         r_refdef.view.matrix = originalmatrix;
7051
7052         CHECKGLERROR
7053 }
7054
7055 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7056 {
7057         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7058         {
7059                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7060                 if (r_timereport_active)
7061                         R_TimeReport("waterworld");
7062         }
7063
7064         // don't let sound skip if going slow
7065         if (r_refdef.scene.extraupdate)
7066                 S_ExtraUpdate ();
7067
7068         R_DrawModelsAddWaterPlanes();
7069         if (r_timereport_active)
7070                 R_TimeReport("watermodels");
7071
7072         if (r_fb.water.numwaterplanes)
7073         {
7074                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7075                 if (r_timereport_active)
7076                         R_TimeReport("waterscenes");
7077         }
7078 }
7079
7080 extern cvar_t cl_locs_show;
7081 static void R_DrawLocs(void);
7082 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7083 static void R_DrawModelDecals(void);
7084 extern cvar_t cl_decals_newsystem;
7085 extern qboolean r_shadow_usingdeferredprepass;
7086 extern int r_shadow_shadowmapatlas_modelshadows_size;
7087 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7088 {
7089         qboolean shadowmapping = false;
7090
7091         if (r_timereport_active)
7092                 R_TimeReport("beginscene");
7093
7094         r_refdef.stats[r_stat_renders]++;
7095
7096         R_UpdateFog();
7097
7098         // don't let sound skip if going slow
7099         if (r_refdef.scene.extraupdate)
7100                 S_ExtraUpdate ();
7101
7102         R_MeshQueue_BeginScene();
7103
7104         R_SkyStartFrame();
7105
7106         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);
7107
7108         if (r_timereport_active)
7109                 R_TimeReport("skystartframe");
7110
7111         if (cl.csqc_vidvars.drawworld)
7112         {
7113                 // don't let sound skip if going slow
7114                 if (r_refdef.scene.extraupdate)
7115                         S_ExtraUpdate ();
7116
7117                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7118                 {
7119                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7120                         if (r_timereport_active)
7121                                 R_TimeReport("worldsky");
7122                 }
7123
7124                 if (R_DrawBrushModelsSky() && r_timereport_active)
7125                         R_TimeReport("bmodelsky");
7126
7127                 if (skyrendermasked && skyrenderlater)
7128                 {
7129                         // we have to force off the water clipping plane while rendering sky
7130                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7131                         R_Sky();
7132                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7133                         if (r_timereport_active)
7134                                 R_TimeReport("sky");
7135                 }
7136         }
7137
7138         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7139         r_shadow_viewfbo = viewfbo;
7140         r_shadow_viewdepthtexture = viewdepthtexture;
7141         r_shadow_viewcolortexture = viewcolortexture;
7142         r_shadow_viewx = viewx;
7143         r_shadow_viewy = viewy;
7144         r_shadow_viewwidth = viewwidth;
7145         r_shadow_viewheight = viewheight;
7146
7147         R_Shadow_PrepareModelShadows();
7148         R_Shadow_PrepareLights();
7149         if (r_timereport_active)
7150                 R_TimeReport("preparelights");
7151
7152         // render all the shadowmaps that will be used for this view
7153         shadowmapping = R_Shadow_ShadowMappingEnabled();
7154         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7155         {
7156                 R_Shadow_DrawShadowMaps();
7157                 if (r_timereport_active)
7158                         R_TimeReport("shadowmaps");
7159         }
7160
7161         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7162         if (r_shadow_usingdeferredprepass)
7163                 R_Shadow_DrawPrepass();
7164
7165         // now we begin the forward pass of the view render
7166         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7167         {
7168                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7169                 if (r_timereport_active)
7170                         R_TimeReport("worlddepth");
7171         }
7172         if (r_depthfirst.integer >= 2)
7173         {
7174                 R_DrawModelsDepth();
7175                 if (r_timereport_active)
7176                         R_TimeReport("modeldepth");
7177         }
7178
7179         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7180         {
7181                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7182                 if (r_timereport_active)
7183                         R_TimeReport("world");
7184         }
7185
7186         // don't let sound skip if going slow
7187         if (r_refdef.scene.extraupdate)
7188                 S_ExtraUpdate ();
7189
7190         R_DrawModels();
7191         if (r_timereport_active)
7192                 R_TimeReport("models");
7193
7194         // don't let sound skip if going slow
7195         if (r_refdef.scene.extraupdate)
7196                 S_ExtraUpdate ();
7197
7198         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7199         {
7200                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7201                 R_Shadow_DrawModelShadows();
7202                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7203                 // don't let sound skip if going slow
7204                 if (r_refdef.scene.extraupdate)
7205                         S_ExtraUpdate ();
7206         }
7207
7208         if (!r_shadow_usingdeferredprepass)
7209         {
7210                 R_Shadow_DrawLights();
7211                 if (r_timereport_active)
7212                         R_TimeReport("rtlights");
7213         }
7214
7215         // don't let sound skip if going slow
7216         if (r_refdef.scene.extraupdate)
7217                 S_ExtraUpdate ();
7218
7219         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7220         {
7221                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7222                 R_Shadow_DrawModelShadows();
7223                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7224                 // don't let sound skip if going slow
7225                 if (r_refdef.scene.extraupdate)
7226                         S_ExtraUpdate ();
7227         }
7228
7229         if (cl.csqc_vidvars.drawworld)
7230         {
7231                 if (cl_decals_newsystem.integer)
7232                 {
7233                         R_DrawModelDecals();
7234                         if (r_timereport_active)
7235                                 R_TimeReport("modeldecals");
7236                 }
7237                 else
7238                 {
7239                         R_DrawDecals();
7240                         if (r_timereport_active)
7241                                 R_TimeReport("decals");
7242                 }
7243
7244                 R_DrawParticles();
7245                 if (r_timereport_active)
7246                         R_TimeReport("particles");
7247
7248                 R_DrawExplosions();
7249                 if (r_timereport_active)
7250                         R_TimeReport("explosions");
7251         }
7252
7253         if (r_refdef.view.showdebug)
7254         {
7255                 if (cl_locs_show.integer)
7256                 {
7257                         R_DrawLocs();
7258                         if (r_timereport_active)
7259                                 R_TimeReport("showlocs");
7260                 }
7261
7262                 if (r_drawportals.integer)
7263                 {
7264                         R_DrawPortals();
7265                         if (r_timereport_active)
7266                                 R_TimeReport("portals");
7267                 }
7268
7269                 if (r_showbboxes_client.value > 0)
7270                 {
7271                         R_DrawEntityBBoxes(CLVM_prog);
7272                         if (r_timereport_active)
7273                                 R_TimeReport("clbboxes");
7274                 }
7275                 if (r_showbboxes.value > 0)
7276                 {
7277                         R_DrawEntityBBoxes(SVVM_prog);
7278                         if (r_timereport_active)
7279                                 R_TimeReport("svbboxes");
7280                 }
7281         }
7282
7283         if (r_transparent.integer)
7284         {
7285                 R_MeshQueue_RenderTransparent();
7286                 if (r_timereport_active)
7287                         R_TimeReport("drawtrans");
7288         }
7289
7290         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))
7291         {
7292                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7293                 if (r_timereport_active)
7294                         R_TimeReport("worlddebug");
7295                 R_DrawModelsDebug();
7296                 if (r_timereport_active)
7297                         R_TimeReport("modeldebug");
7298         }
7299
7300         if (cl.csqc_vidvars.drawworld)
7301         {
7302                 R_Shadow_DrawCoronas();
7303                 if (r_timereport_active)
7304                         R_TimeReport("coronas");
7305         }
7306
7307 #if 0
7308         {
7309                 GL_DepthTest(false);
7310                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7311                 GL_Color(1, 1, 1, 1);
7312                 qglBegin(GL_POLYGON);
7313                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7314                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7315                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7316                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7317                 qglEnd();
7318                 qglBegin(GL_POLYGON);
7319                 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]);
7320                 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]);
7321                 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]);
7322                 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]);
7323                 qglEnd();
7324                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7325         }
7326 #endif
7327
7328         // don't let sound skip if going slow
7329         if (r_refdef.scene.extraupdate)
7330                 S_ExtraUpdate ();
7331 }
7332
7333 static const unsigned short bboxelements[36] =
7334 {
7335         5, 1, 3, 5, 3, 7,
7336         6, 2, 0, 6, 0, 4,
7337         7, 3, 2, 7, 2, 6,
7338         4, 0, 1, 4, 1, 5,
7339         4, 5, 7, 4, 7, 6,
7340         1, 0, 2, 1, 2, 3,
7341 };
7342
7343 #define BBOXEDGES 13
7344 static const float bboxedges[BBOXEDGES][6] = 
7345 {
7346         // whole box
7347         { 0, 0, 0, 1, 1, 1 },
7348         // bottom edges
7349         { 0, 0, 0, 0, 1, 0 },
7350         { 0, 0, 0, 1, 0, 0 },
7351         { 0, 1, 0, 1, 1, 0 },
7352         { 1, 0, 0, 1, 1, 0 },
7353         // top edges
7354         { 0, 0, 1, 0, 1, 1 },
7355         { 0, 0, 1, 1, 0, 1 },
7356         { 0, 1, 1, 1, 1, 1 },
7357         { 1, 0, 1, 1, 1, 1 },
7358         // vertical edges
7359         { 0, 0, 0, 0, 0, 1 },
7360         { 1, 0, 0, 1, 0, 1 },
7361         { 0, 1, 0, 0, 1, 1 },
7362         { 1, 1, 0, 1, 1, 1 },
7363 };
7364
7365 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7366 {
7367         int numvertices = BBOXEDGES * 8;
7368         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7369         int numtriangles = BBOXEDGES * 12;
7370         unsigned short elements[BBOXEDGES * 36];
7371         int i, edge;
7372         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7373
7374         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7375
7376         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7377         GL_DepthMask(false);
7378         GL_DepthRange(0, 1);
7379         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7380
7381         for (edge = 0; edge < BBOXEDGES; edge++)
7382         {
7383                 for (i = 0; i < 3; i++)
7384                 {
7385                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7386                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7387                 }
7388                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7389                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7390                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7391                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7392                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7393                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7394                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7395                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7396                 for (i = 0; i < 36; i++)
7397                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7398         }
7399         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7400         if (r_refdef.fogenabled)
7401         {
7402                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7403                 {
7404                         f1 = RSurf_FogVertex(v);
7405                         f2 = 1 - f1;
7406                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7407                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7408                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7409                 }
7410         }
7411         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7412         R_Mesh_ResetTextureState();
7413         R_SetupShader_Generic_NoTexture(false, false);
7414         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7415 }
7416
7417 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7418 {
7419         // hacky overloading of the parameters
7420         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7421         int i;
7422         float color[4];
7423         prvm_edict_t *edict;
7424
7425         GL_CullFace(GL_NONE);
7426         R_SetupShader_Generic_NoTexture(false, false);
7427
7428         for (i = 0;i < numsurfaces;i++)
7429         {
7430                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7431                 switch ((int)PRVM_serveredictfloat(edict, solid))
7432                 {
7433                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7434                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7435                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7436                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7437                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7438                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7439                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7440                 }
7441                 if (prog == CLVM_prog)
7442                         color[3] *= r_showbboxes_client.value;
7443                 else
7444                         color[3] *= r_showbboxes.value;
7445                 color[3] = bound(0, color[3], 1);
7446                 GL_DepthTest(!r_showdisabledepthtest.integer);
7447                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7448         }
7449 }
7450
7451 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7452 {
7453         int i;
7454         prvm_edict_t *edict;
7455         vec3_t center;
7456
7457         if (prog == NULL)
7458                 return;
7459
7460         for (i = 0; i < prog->num_edicts; i++)
7461         {
7462                 edict = PRVM_EDICT_NUM(i);
7463                 if (edict->priv.server->free)
7464                         continue;
7465                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7466                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7467                         continue;
7468                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7469                         continue;
7470                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7471                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7472         }
7473 }
7474
7475 static const int nomodelelement3i[24] =
7476 {
7477         5, 2, 0,
7478         5, 1, 2,
7479         5, 0, 3,
7480         5, 3, 1,
7481         0, 2, 4,
7482         2, 1, 4,
7483         3, 0, 4,
7484         1, 3, 4
7485 };
7486
7487 static const unsigned short nomodelelement3s[24] =
7488 {
7489         5, 2, 0,
7490         5, 1, 2,
7491         5, 0, 3,
7492         5, 3, 1,
7493         0, 2, 4,
7494         2, 1, 4,
7495         3, 0, 4,
7496         1, 3, 4
7497 };
7498
7499 static const float nomodelvertex3f[6*3] =
7500 {
7501         -16,   0,   0,
7502          16,   0,   0,
7503           0, -16,   0,
7504           0,  16,   0,
7505           0,   0, -16,
7506           0,   0,  16
7507 };
7508
7509 static const float nomodelcolor4f[6*4] =
7510 {
7511         0.0f, 0.0f, 0.5f, 1.0f,
7512         0.0f, 0.0f, 0.5f, 1.0f,
7513         0.0f, 0.5f, 0.0f, 1.0f,
7514         0.0f, 0.5f, 0.0f, 1.0f,
7515         0.5f, 0.0f, 0.0f, 1.0f,
7516         0.5f, 0.0f, 0.0f, 1.0f
7517 };
7518
7519 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7520 {
7521         int i;
7522         float f1, f2, *c;
7523         float color4f[6*4];
7524
7525         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);
7526
7527         // this is only called once per entity so numsurfaces is always 1, and
7528         // surfacelist is always {0}, so this code does not handle batches
7529
7530         if (rsurface.ent_flags & RENDER_ADDITIVE)
7531         {
7532                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7533                 GL_DepthMask(false);
7534         }
7535         else if (ent->alpha < 1)
7536         {
7537                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7538                 GL_DepthMask(false);
7539         }
7540         else
7541         {
7542                 GL_BlendFunc(GL_ONE, GL_ZERO);
7543                 GL_DepthMask(true);
7544         }
7545         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7546         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7547         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7548         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7549         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7550         for (i = 0, c = color4f;i < 6;i++, c += 4)
7551         {
7552                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7553                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7554                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7555                 c[3] *= ent->alpha;
7556         }
7557         if (r_refdef.fogenabled)
7558         {
7559                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7560                 {
7561                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7562                         f2 = 1 - f1;
7563                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7564                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7565                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7566                 }
7567         }
7568 //      R_Mesh_ResetTextureState();
7569         R_SetupShader_Generic_NoTexture(false, false);
7570         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7571         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7572 }
7573
7574 void R_DrawNoModel(entity_render_t *ent)
7575 {
7576         vec3_t org;
7577         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7578         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7579                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7580         else
7581                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7582 }
7583
7584 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7585 {
7586         vec3_t right1, right2, diff, normal;
7587
7588         VectorSubtract (org2, org1, normal);
7589
7590         // calculate 'right' vector for start
7591         VectorSubtract (r_refdef.view.origin, org1, diff);
7592         CrossProduct (normal, diff, right1);
7593         VectorNormalize (right1);
7594
7595         // calculate 'right' vector for end
7596         VectorSubtract (r_refdef.view.origin, org2, diff);
7597         CrossProduct (normal, diff, right2);
7598         VectorNormalize (right2);
7599
7600         vert[ 0] = org1[0] + width * right1[0];
7601         vert[ 1] = org1[1] + width * right1[1];
7602         vert[ 2] = org1[2] + width * right1[2];
7603         vert[ 3] = org1[0] - width * right1[0];
7604         vert[ 4] = org1[1] - width * right1[1];
7605         vert[ 5] = org1[2] - width * right1[2];
7606         vert[ 6] = org2[0] - width * right2[0];
7607         vert[ 7] = org2[1] - width * right2[1];
7608         vert[ 8] = org2[2] - width * right2[2];
7609         vert[ 9] = org2[0] + width * right2[0];
7610         vert[10] = org2[1] + width * right2[1];
7611         vert[11] = org2[2] + width * right2[2];
7612 }
7613
7614 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)
7615 {
7616         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7617         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7618         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7619         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7620         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7621         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7622         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7623         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7624         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7625         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7626         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7627         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7628 }
7629
7630 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7631 {
7632         int i;
7633         float *vertex3f;
7634         float v[3];
7635         VectorSet(v, x, y, z);
7636         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7637                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7638                         break;
7639         if (i == mesh->numvertices)
7640         {
7641                 if (mesh->numvertices < mesh->maxvertices)
7642                 {
7643                         VectorCopy(v, vertex3f);
7644                         mesh->numvertices++;
7645                 }
7646                 return mesh->numvertices;
7647         }
7648         else
7649                 return i;
7650 }
7651
7652 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7653 {
7654         int i;
7655         int *e, element[3];
7656         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7657         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7658         e = mesh->element3i + mesh->numtriangles * 3;
7659         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7660         {
7661                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7662                 if (mesh->numtriangles < mesh->maxtriangles)
7663                 {
7664                         *e++ = element[0];
7665                         *e++ = element[1];
7666                         *e++ = element[2];
7667                         mesh->numtriangles++;
7668                 }
7669                 element[1] = element[2];
7670         }
7671 }
7672
7673 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7674 {
7675         int i;
7676         int *e, element[3];
7677         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7678         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7679         e = mesh->element3i + mesh->numtriangles * 3;
7680         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7681         {
7682                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7683                 if (mesh->numtriangles < mesh->maxtriangles)
7684                 {
7685                         *e++ = element[0];
7686                         *e++ = element[1];
7687                         *e++ = element[2];
7688                         mesh->numtriangles++;
7689                 }
7690                 element[1] = element[2];
7691         }
7692 }
7693
7694 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7695 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7696 {
7697         int planenum, planenum2;
7698         int w;
7699         int tempnumpoints;
7700         mplane_t *plane, *plane2;
7701         double maxdist;
7702         double temppoints[2][256*3];
7703         // figure out how large a bounding box we need to properly compute this brush
7704         maxdist = 0;
7705         for (w = 0;w < numplanes;w++)
7706                 maxdist = max(maxdist, fabs(planes[w].dist));
7707         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7708         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7709         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7710         {
7711                 w = 0;
7712                 tempnumpoints = 4;
7713                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7714                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7715                 {
7716                         if (planenum2 == planenum)
7717                                 continue;
7718                         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);
7719                         w = !w;
7720                 }
7721                 if (tempnumpoints < 3)
7722                         continue;
7723                 // generate elements forming a triangle fan for this polygon
7724                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7725         }
7726 }
7727
7728 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)
7729 {
7730         texturelayer_t *layer;
7731         layer = t->currentlayers + t->currentnumlayers++;
7732         layer->type = type;
7733         layer->depthmask = depthmask;
7734         layer->blendfunc1 = blendfunc1;
7735         layer->blendfunc2 = blendfunc2;
7736         layer->texture = texture;
7737         layer->texmatrix = *matrix;
7738         layer->color[0] = r;
7739         layer->color[1] = g;
7740         layer->color[2] = b;
7741         layer->color[3] = a;
7742 }
7743
7744 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7745 {
7746         if(parms[0] == 0 && parms[1] == 0)
7747                 return false;
7748         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7749                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7750                         return false;
7751         return true;
7752 }
7753
7754 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7755 {
7756         double index, f;
7757         index = parms[2] + rsurface.shadertime * parms[3];
7758         index -= floor(index);
7759         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7760         {
7761         default:
7762         case Q3WAVEFUNC_NONE:
7763         case Q3WAVEFUNC_NOISE:
7764         case Q3WAVEFUNC_COUNT:
7765                 f = 0;
7766                 break;
7767         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7768         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7769         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7770         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7771         case Q3WAVEFUNC_TRIANGLE:
7772                 index *= 4;
7773                 f = index - floor(index);
7774                 if (index < 1)
7775                 {
7776                         // f = f;
7777                 }
7778                 else if (index < 2)
7779                         f = 1 - f;
7780                 else if (index < 3)
7781                         f = -f;
7782                 else
7783                         f = -(1 - f);
7784                 break;
7785         }
7786         f = parms[0] + parms[1] * f;
7787         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7788                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7789         return (float) f;
7790 }
7791
7792 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7793 {
7794         int w, h, idx;
7795         float shadertime;
7796         float f;
7797         float offsetd[2];
7798         float tcmat[12];
7799         matrix4x4_t matrix, temp;
7800         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7801         // it's better to have one huge fixup every 9 hours than gradual
7802         // degradation over time which looks consistently bad after many hours.
7803         //
7804         // tcmod scroll in particular suffers from this degradation which can't be
7805         // effectively worked around even with floor() tricks because we don't
7806         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7807         // a workaround involving floor() would be incorrect anyway...
7808         shadertime = rsurface.shadertime;
7809         if (shadertime >= 32768.0f)
7810                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7811         switch(tcmod->tcmod)
7812         {
7813                 case Q3TCMOD_COUNT:
7814                 case Q3TCMOD_NONE:
7815                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7816                                 matrix = r_waterscrollmatrix;
7817                         else
7818                                 matrix = identitymatrix;
7819                         break;
7820                 case Q3TCMOD_ENTITYTRANSLATE:
7821                         // this is used in Q3 to allow the gamecode to control texcoord
7822                         // scrolling on the entity, which is not supported in darkplaces yet.
7823                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7824                         break;
7825                 case Q3TCMOD_ROTATE:
7826                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7827                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7828                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7829                         break;
7830                 case Q3TCMOD_SCALE:
7831                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7832                         break;
7833                 case Q3TCMOD_SCROLL:
7834                         // this particular tcmod is a "bug for bug" compatible one with regards to
7835                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7836                         // specifically did the wrapping and so we must mimic that...
7837                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7838                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7839                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7840                         break;
7841                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7842                         w = (int) tcmod->parms[0];
7843                         h = (int) tcmod->parms[1];
7844                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7845                         f = f - floor(f);
7846                         idx = (int) floor(f * w * h);
7847                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7848                         break;
7849                 case Q3TCMOD_STRETCH:
7850                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7851                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7852                         break;
7853                 case Q3TCMOD_TRANSFORM:
7854                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7855                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7856                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7857                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7858                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7859                         break;
7860                 case Q3TCMOD_TURBULENT:
7861                         // this is handled in the RSurf_PrepareVertices function
7862                         matrix = identitymatrix;
7863                         break;
7864         }
7865         temp = *texmatrix;
7866         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7867 }
7868
7869 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7870 {
7871         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7872         char name[MAX_QPATH];
7873         skinframe_t *skinframe;
7874         unsigned char pixels[296*194];
7875         strlcpy(cache->name, skinname, sizeof(cache->name));
7876         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7877         if (developer_loading.integer)
7878                 Con_Printf("loading %s\n", name);
7879         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7880         if (!skinframe || !skinframe->base)
7881         {
7882                 unsigned char *f;
7883                 fs_offset_t filesize;
7884                 skinframe = NULL;
7885                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7886                 if (f)
7887                 {
7888                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7889                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7890                         Mem_Free(f);
7891                 }
7892         }
7893         cache->skinframe = skinframe;
7894 }
7895
7896 texture_t *R_GetCurrentTexture(texture_t *t)
7897 {
7898         int i, q;
7899         const entity_render_t *ent = rsurface.entity;
7900         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7901         q3shaderinfo_layer_tcmod_t *tcmod;
7902         float specularscale = 0.0f;
7903
7904         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7905                 return t->currentframe;
7906         t->update_lastrenderframe = r_textureframe;
7907         t->update_lastrenderentity = (void *)ent;
7908
7909         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7910                 t->camera_entity = ent->entitynumber;
7911         else
7912                 t->camera_entity = 0;
7913
7914         // switch to an alternate material if this is a q1bsp animated material
7915         {
7916                 texture_t *texture = t;
7917                 int s = rsurface.ent_skinnum;
7918                 if ((unsigned int)s >= (unsigned int)model->numskins)
7919                         s = 0;
7920                 if (model->skinscenes)
7921                 {
7922                         if (model->skinscenes[s].framecount > 1)
7923                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7924                         else
7925                                 s = model->skinscenes[s].firstframe;
7926                 }
7927                 if (s > 0)
7928                         t = t + s * model->num_surfaces;
7929                 if (t->animated)
7930                 {
7931                         // use an alternate animation if the entity's frame is not 0,
7932                         // and only if the texture has an alternate animation
7933                         if (t->animated == 2) // q2bsp
7934                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7935                         else if (rsurface.ent_alttextures && t->anim_total[1])
7936                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7937                         else
7938                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7939                 }
7940                 texture->currentframe = t;
7941         }
7942
7943         // update currentskinframe to be a qw skin or animation frame
7944         if (rsurface.ent_qwskin >= 0)
7945         {
7946                 i = rsurface.ent_qwskin;
7947                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7948                 {
7949                         r_qwskincache_size = cl.maxclients;
7950                         if (r_qwskincache)
7951                                 Mem_Free(r_qwskincache);
7952                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7953                 }
7954                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7955                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7956                 t->currentskinframe = r_qwskincache[i].skinframe;
7957                 if (t->materialshaderpass && t->currentskinframe == NULL)
7958                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7959         }
7960         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7961                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7962         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7963                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7964
7965         t->currentmaterialflags = t->basematerialflags;
7966         t->currentalpha = rsurface.entity->alpha * t->basealpha;
7967         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7968                 t->currentalpha *= r_wateralpha.value;
7969         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7970                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7971         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7972                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7973
7974         // decide on which type of lighting to use for this surface
7975         if (rsurface.entity->render_modellight_forced)
7976                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7977         if (rsurface.entity->render_rtlight_disabled)
7978                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
7979         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
7980         {
7981                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
7982                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
7983                 for (q = 0; q < 3; q++)
7984                 {
7985                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
7986                         t->render_modellight_lightdir[q] = q == 2;
7987                         t->render_modellight_ambient[q] = 1;
7988                         t->render_modellight_diffuse[q] = 0;
7989                         t->render_modellight_specular[q] = 0;
7990                         t->render_lightmap_ambient[q] = 0;
7991                         t->render_lightmap_diffuse[q] = 0;
7992                         t->render_lightmap_specular[q] = 0;
7993                         t->render_rtlight_diffuse[q] = 0;
7994                         t->render_rtlight_specular[q] = 0;
7995                 }
7996         }
7997         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
7998         {
7999                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8000                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8001                 for (q = 0; q < 3; q++)
8002                 {
8003                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8004                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8005                         t->render_modellight_lightdir[q] = q == 2;
8006                         t->render_modellight_diffuse[q] = 0;
8007                         t->render_modellight_specular[q] = 0;
8008                         t->render_lightmap_ambient[q] = 0;
8009                         t->render_lightmap_diffuse[q] = 0;
8010                         t->render_lightmap_specular[q] = 0;
8011                         t->render_rtlight_diffuse[q] = 0;
8012                         t->render_rtlight_specular[q] = 0;
8013                 }
8014         }
8015         else if (FAKELIGHT_ENABLED)
8016         {
8017                 // no modellight if using fakelight for the map
8018                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8019                 for (q = 0; q < 3; q++)
8020                 {
8021                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8022                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8023                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8024                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8025                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8026                         t->render_lightmap_ambient[q] = 0;
8027                         t->render_lightmap_diffuse[q] = 0;
8028                         t->render_lightmap_specular[q] = 0;
8029                         t->render_rtlight_diffuse[q] = 0;
8030                         t->render_rtlight_specular[q] = 0;
8031                 }
8032         }
8033         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8034         {
8035                 // ambient + single direction light (modellight)
8036                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8037                 for (q = 0; q < 3; q++)
8038                 {
8039                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8040                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8041                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8042                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8043                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8044                         t->render_lightmap_ambient[q] = 0;
8045                         t->render_lightmap_diffuse[q] = 0;
8046                         t->render_lightmap_specular[q] = 0;
8047                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8048                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8049                 }
8050         }
8051         else
8052         {
8053                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8054                 for (q = 0; q < 3; q++)
8055                 {
8056                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8057                         t->render_modellight_lightdir[q] = q == 2;
8058                         t->render_modellight_ambient[q] = 0;
8059                         t->render_modellight_diffuse[q] = 0;
8060                         t->render_modellight_specular[q] = 0;
8061                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8062                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8063                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8064                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8065                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8066                 }
8067         }
8068
8069         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8070         {
8071                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8072                 // attribute, we punt it to the lightmap path and hope for the best,
8073                 // but lighting doesn't work.
8074                 //
8075                 // FIXME: this is fine for effects but CSQC polygons should be subject
8076                 // to lighting.
8077                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8078                 for (q = 0; q < 3; q++)
8079                 {
8080                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8081                         t->render_modellight_lightdir[q] = q == 2;
8082                         t->render_modellight_ambient[q] = 0;
8083                         t->render_modellight_diffuse[q] = 0;
8084                         t->render_modellight_specular[q] = 0;
8085                         t->render_lightmap_ambient[q] = 0;
8086                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8087                         t->render_lightmap_specular[q] = 0;
8088                         t->render_rtlight_diffuse[q] = 0;
8089                         t->render_rtlight_specular[q] = 0;
8090                 }
8091         }
8092
8093         for (q = 0; q < 3; q++)
8094         {
8095                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8096                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8097         }
8098
8099         if (rsurface.ent_flags & RENDER_ADDITIVE)
8100                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8101         else if (t->currentalpha < 1)
8102                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8103         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8104         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8105                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8106         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8107                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8108         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8109                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8110         if (t->backgroundshaderpass)
8111                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8112         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8113         {
8114                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8115                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8116         }
8117         else
8118                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8119         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8120         {
8121                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8122                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8123         }
8124         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8125                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8126
8127         // there is no tcmod
8128         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8129         {
8130                 t->currenttexmatrix = r_waterscrollmatrix;
8131                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8132         }
8133         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8134         {
8135                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8136                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8137         }
8138
8139         if (t->materialshaderpass)
8140                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8141                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8142
8143         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8144         if (t->currentskinframe->qpixels)
8145                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8146         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8147         if (!t->basetexture)
8148                 t->basetexture = r_texture_notexture;
8149         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8150         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8151         t->nmaptexture = t->currentskinframe->nmap;
8152         if (!t->nmaptexture)
8153                 t->nmaptexture = r_texture_blanknormalmap;
8154         t->glosstexture = r_texture_black;
8155         t->glowtexture = t->currentskinframe->glow;
8156         t->fogtexture = t->currentskinframe->fog;
8157         t->reflectmasktexture = t->currentskinframe->reflect;
8158         if (t->backgroundshaderpass)
8159         {
8160                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8161                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8162                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8163                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8164                 t->backgroundglosstexture = r_texture_black;
8165                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8166                 if (!t->backgroundnmaptexture)
8167                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8168                 // make sure that if glow is going to be used, both textures are not NULL
8169                 if (!t->backgroundglowtexture && t->glowtexture)
8170                         t->backgroundglowtexture = r_texture_black;
8171                 if (!t->glowtexture && t->backgroundglowtexture)
8172                         t->glowtexture = r_texture_black;
8173         }
8174         else
8175         {
8176                 t->backgroundbasetexture = r_texture_white;
8177                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8178                 t->backgroundglosstexture = r_texture_black;
8179                 t->backgroundglowtexture = NULL;
8180         }
8181         t->specularpower = r_shadow_glossexponent.value;
8182         // TODO: store reference values for these in the texture?
8183         if (r_shadow_gloss.integer > 0)
8184         {
8185                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8186                 {
8187                         if (r_shadow_glossintensity.value > 0)
8188                         {
8189                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8190                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8191                                 specularscale = r_shadow_glossintensity.value;
8192                         }
8193                 }
8194                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8195                 {
8196                         t->glosstexture = r_texture_white;
8197                         t->backgroundglosstexture = r_texture_white;
8198                         specularscale = r_shadow_gloss2intensity.value;
8199                         t->specularpower = r_shadow_gloss2exponent.value;
8200                 }
8201         }
8202         specularscale *= t->specularscalemod;
8203         t->specularpower *= t->specularpowermod;
8204
8205         // lightmaps mode looks bad with dlights using actual texturing, so turn
8206         // off the colormap and glossmap, but leave the normalmap on as it still
8207         // accurately represents the shading involved
8208         if (gl_lightmaps.integer)
8209         {
8210                 t->basetexture = r_texture_grey128;
8211                 t->pantstexture = r_texture_black;
8212                 t->shirttexture = r_texture_black;
8213                 if (gl_lightmaps.integer < 2)
8214                         t->nmaptexture = r_texture_blanknormalmap;
8215                 t->glosstexture = r_texture_black;
8216                 t->glowtexture = NULL;
8217                 t->fogtexture = NULL;
8218                 t->reflectmasktexture = NULL;
8219                 t->backgroundbasetexture = NULL;
8220                 if (gl_lightmaps.integer < 2)
8221                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8222                 t->backgroundglosstexture = r_texture_black;
8223                 t->backgroundglowtexture = NULL;
8224                 specularscale = 0;
8225                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8226         }
8227
8228         if (specularscale != 1.0f)
8229         {
8230                 for (q = 0; q < 3; q++)
8231                 {
8232                         t->render_modellight_specular[q] *= specularscale;
8233                         t->render_lightmap_specular[q] *= specularscale;
8234                         t->render_rtlight_specular[q] *= specularscale;
8235                 }
8236         }
8237
8238         t->currentnumlayers = 0;
8239         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8240         {
8241                 int blendfunc1, blendfunc2;
8242                 qboolean depthmask;
8243                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8244                 {
8245                         blendfunc1 = GL_SRC_ALPHA;
8246                         blendfunc2 = GL_ONE;
8247                 }
8248                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8249                 {
8250                         blendfunc1 = GL_SRC_ALPHA;
8251                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8252                 }
8253                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8254                 {
8255                         blendfunc1 = t->customblendfunc[0];
8256                         blendfunc2 = t->customblendfunc[1];
8257                 }
8258                 else
8259                 {
8260                         blendfunc1 = GL_ONE;
8261                         blendfunc2 = GL_ZERO;
8262                 }
8263                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8264                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8265                 {
8266                         // basic lit geometry
8267                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
8268                         // add pants/shirt if needed
8269                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8270                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, 2 * t->render_colormap_pants[0], 2 * t->render_colormap_pants[1], 2 * t->render_colormap_pants[2], t->currentalpha);
8271                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8272                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, 2 * t->render_colormap_shirt[0], 2 * t->render_colormap_shirt[1], 2 * t->render_colormap_shirt[2], t->currentalpha);
8273                 }
8274                 else
8275                 {
8276                         // basic lit geometry
8277                         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);
8278                         // add pants/shirt if needed
8279                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8280                                 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);
8281                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8282                                 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);
8283                         // now add ambient passes if needed
8284                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8285                         {
8286                                 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);
8287                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8288                                         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);
8289                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8290                                         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);
8291                         }
8292                 }
8293                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8294                         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);
8295                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8296                 {
8297                         // if this is opaque use alpha blend which will darken the earlier
8298                         // passes cheaply.
8299                         //
8300                         // if this is an alpha blended material, all the earlier passes
8301                         // were darkened by fog already, so we only need to add the fog
8302                         // color ontop through the fog mask texture
8303                         //
8304                         // if this is an additive blended material, all the earlier passes
8305                         // were darkened by fog already, and we should not add fog color
8306                         // (because the background was not darkened, there is no fog color
8307                         // that was lost behind it).
8308                         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);
8309                 }
8310         }
8311
8312         return t;
8313 }
8314
8315 rsurfacestate_t rsurface;
8316
8317 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8318 {
8319         dp_model_t *model = ent->model;
8320         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8321         //      return;
8322         rsurface.entity = (entity_render_t *)ent;
8323         rsurface.skeleton = ent->skeleton;
8324         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8325         rsurface.ent_skinnum = ent->skinnum;
8326         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;
8327         rsurface.ent_flags = ent->flags;
8328         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8329                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8330         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8331         rsurface.matrix = ent->matrix;
8332         rsurface.inversematrix = ent->inversematrix;
8333         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8334         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8335         R_EntityMatrix(&rsurface.matrix);
8336         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8337         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8338         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8339         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8340         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8341         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8342         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8343         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8344         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8345         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8346         if (ent->model->brush.submodel && !prepass)
8347         {
8348                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8349                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8350         }
8351         // if the animcache code decided it should use the shader path, skip the deform step
8352         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8353         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8354         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8355         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8356         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8357         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8358         {
8359                 if (ent->animcache_vertex3f)
8360                 {
8361                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8362                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8363                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8364                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8365                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8366                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8367                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8368                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8369                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8370                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8371                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8372                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8373                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8374                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8375                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8376                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8377                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8378                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8379                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8380                 }
8381                 else if (wanttangents)
8382                 {
8383                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8384                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8385                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8386                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8387                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8388                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8389                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8390                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8391                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8392                         rsurface.modelvertexmesh = NULL;
8393                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8394                         rsurface.modelvertexmesh_bufferoffset = 0;
8395                         rsurface.modelvertex3f_vertexbuffer = NULL;
8396                         rsurface.modelvertex3f_bufferoffset = 0;
8397                         rsurface.modelvertex3f_vertexbuffer = 0;
8398                         rsurface.modelvertex3f_bufferoffset = 0;
8399                         rsurface.modelsvector3f_vertexbuffer = 0;
8400                         rsurface.modelsvector3f_bufferoffset = 0;
8401                         rsurface.modeltvector3f_vertexbuffer = 0;
8402                         rsurface.modeltvector3f_bufferoffset = 0;
8403                         rsurface.modelnormal3f_vertexbuffer = 0;
8404                         rsurface.modelnormal3f_bufferoffset = 0;
8405                 }
8406                 else if (wantnormals)
8407                 {
8408                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8409                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8410                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8411                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8412                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413                         rsurface.modelsvector3f = NULL;
8414                         rsurface.modeltvector3f = NULL;
8415                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8417                         rsurface.modelvertexmesh = NULL;
8418                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8419                         rsurface.modelvertexmesh_bufferoffset = 0;
8420                         rsurface.modelvertex3f_vertexbuffer = NULL;
8421                         rsurface.modelvertex3f_bufferoffset = 0;
8422                         rsurface.modelvertex3f_vertexbuffer = 0;
8423                         rsurface.modelvertex3f_bufferoffset = 0;
8424                         rsurface.modelsvector3f_vertexbuffer = 0;
8425                         rsurface.modelsvector3f_bufferoffset = 0;
8426                         rsurface.modeltvector3f_vertexbuffer = 0;
8427                         rsurface.modeltvector3f_bufferoffset = 0;
8428                         rsurface.modelnormal3f_vertexbuffer = 0;
8429                         rsurface.modelnormal3f_bufferoffset = 0;
8430                 }
8431                 else
8432                 {
8433                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8434                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8435                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8436                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8437                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8438                         rsurface.modelsvector3f = NULL;
8439                         rsurface.modeltvector3f = NULL;
8440                         rsurface.modelnormal3f = NULL;
8441                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8442                         rsurface.modelvertexmesh = NULL;
8443                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8444                         rsurface.modelvertexmesh_bufferoffset = 0;
8445                         rsurface.modelvertex3f_vertexbuffer = NULL;
8446                         rsurface.modelvertex3f_bufferoffset = 0;
8447                         rsurface.modelvertex3f_vertexbuffer = 0;
8448                         rsurface.modelvertex3f_bufferoffset = 0;
8449                         rsurface.modelsvector3f_vertexbuffer = 0;
8450                         rsurface.modelsvector3f_bufferoffset = 0;
8451                         rsurface.modeltvector3f_vertexbuffer = 0;
8452                         rsurface.modeltvector3f_bufferoffset = 0;
8453                         rsurface.modelnormal3f_vertexbuffer = 0;
8454                         rsurface.modelnormal3f_bufferoffset = 0;
8455                 }
8456                 rsurface.modelgeneratedvertex = true;
8457         }
8458         else
8459         {
8460                 if (rsurface.entityskeletaltransform3x4)
8461                 {
8462                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8463                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8464                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8465                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8466                 }
8467                 else
8468                 {
8469                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8470                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8471                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8472                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8473                 }
8474                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8475                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8476                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8477                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8478                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8479                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8480                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8481                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8482                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8483                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8484                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8485                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8486                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8487                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8489                 rsurface.modelgeneratedvertex = false;
8490         }
8491         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8492         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8493         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8494         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8495         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8496         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8497         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8498         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8499         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8500         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8501         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8502         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8503         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8504         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8506         rsurface.modelelement3i = model->surfmesh.data_element3i;
8507         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8508         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8509         rsurface.modelelement3s = model->surfmesh.data_element3s;
8510         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8511         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8512         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8513         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8514         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8515         rsurface.modelsurfaces = model->data_surfaces;
8516         rsurface.batchgeneratedvertex = false;
8517         rsurface.batchfirstvertex = 0;
8518         rsurface.batchnumvertices = 0;
8519         rsurface.batchfirsttriangle = 0;
8520         rsurface.batchnumtriangles = 0;
8521         rsurface.batchvertex3f  = NULL;
8522         rsurface.batchvertex3f_vertexbuffer = NULL;
8523         rsurface.batchvertex3f_bufferoffset = 0;
8524         rsurface.batchsvector3f = NULL;
8525         rsurface.batchsvector3f_vertexbuffer = NULL;
8526         rsurface.batchsvector3f_bufferoffset = 0;
8527         rsurface.batchtvector3f = NULL;
8528         rsurface.batchtvector3f_vertexbuffer = NULL;
8529         rsurface.batchtvector3f_bufferoffset = 0;
8530         rsurface.batchnormal3f  = NULL;
8531         rsurface.batchnormal3f_vertexbuffer = NULL;
8532         rsurface.batchnormal3f_bufferoffset = 0;
8533         rsurface.batchlightmapcolor4f = NULL;
8534         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8535         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8536         rsurface.batchtexcoordtexture2f = NULL;
8537         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8538         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8539         rsurface.batchtexcoordlightmap2f = NULL;
8540         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8541         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8542         rsurface.batchskeletalindex4ub = NULL;
8543         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8544         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8545         rsurface.batchskeletalweight4ub = NULL;
8546         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8547         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8548         rsurface.batchvertexmesh = NULL;
8549         rsurface.batchvertexmesh_vertexbuffer = NULL;
8550         rsurface.batchvertexmesh_bufferoffset = 0;
8551         rsurface.batchelement3i = NULL;
8552         rsurface.batchelement3i_indexbuffer = NULL;
8553         rsurface.batchelement3i_bufferoffset = 0;
8554         rsurface.batchelement3s = NULL;
8555         rsurface.batchelement3s_indexbuffer = NULL;
8556         rsurface.batchelement3s_bufferoffset = 0;
8557         rsurface.passcolor4f = NULL;
8558         rsurface.passcolor4f_vertexbuffer = NULL;
8559         rsurface.passcolor4f_bufferoffset = 0;
8560         rsurface.forcecurrenttextureupdate = false;
8561 }
8562
8563 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)
8564 {
8565         rsurface.entity = r_refdef.scene.worldentity;
8566         rsurface.skeleton = NULL;
8567         rsurface.ent_skinnum = 0;
8568         rsurface.ent_qwskin = -1;
8569         rsurface.ent_flags = entflags;
8570         rsurface.shadertime = r_refdef.scene.time - shadertime;
8571         rsurface.modelnumvertices = numvertices;
8572         rsurface.modelnumtriangles = numtriangles;
8573         rsurface.matrix = *matrix;
8574         rsurface.inversematrix = *inversematrix;
8575         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8576         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8577         R_EntityMatrix(&rsurface.matrix);
8578         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8579         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8580         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8581         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8582         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8583         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8584         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8585         rsurface.frameblend[0].lerp = 1;
8586         rsurface.ent_alttextures = false;
8587         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8588         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8589         rsurface.entityskeletaltransform3x4 = NULL;
8590         rsurface.entityskeletaltransform3x4buffer = NULL;
8591         rsurface.entityskeletaltransform3x4offset = 0;
8592         rsurface.entityskeletaltransform3x4size = 0;
8593         rsurface.entityskeletalnumtransforms = 0;
8594         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8595         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8596         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8597         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8598         if (wanttangents)
8599         {
8600                 rsurface.modelvertex3f = (float *)vertex3f;
8601                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8602                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8603                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8604         }
8605         else if (wantnormals)
8606         {
8607                 rsurface.modelvertex3f = (float *)vertex3f;
8608                 rsurface.modelsvector3f = NULL;
8609                 rsurface.modeltvector3f = NULL;
8610                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8611         }
8612         else
8613         {
8614                 rsurface.modelvertex3f = (float *)vertex3f;
8615                 rsurface.modelsvector3f = NULL;
8616                 rsurface.modeltvector3f = NULL;
8617                 rsurface.modelnormal3f = NULL;
8618         }
8619         rsurface.modelvertexmesh = NULL;
8620         rsurface.modelvertexmesh_vertexbuffer = NULL;
8621         rsurface.modelvertexmesh_bufferoffset = 0;
8622         rsurface.modelvertex3f_vertexbuffer = 0;
8623         rsurface.modelvertex3f_bufferoffset = 0;
8624         rsurface.modelsvector3f_vertexbuffer = 0;
8625         rsurface.modelsvector3f_bufferoffset = 0;
8626         rsurface.modeltvector3f_vertexbuffer = 0;
8627         rsurface.modeltvector3f_bufferoffset = 0;
8628         rsurface.modelnormal3f_vertexbuffer = 0;
8629         rsurface.modelnormal3f_bufferoffset = 0;
8630         rsurface.modelgeneratedvertex = true;
8631         rsurface.modellightmapcolor4f  = (float *)color4f;
8632         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8633         rsurface.modellightmapcolor4f_bufferoffset = 0;
8634         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8635         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8636         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8637         rsurface.modeltexcoordlightmap2f  = NULL;
8638         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8639         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8640         rsurface.modelskeletalindex4ub = NULL;
8641         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8642         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8643         rsurface.modelskeletalweight4ub = NULL;
8644         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8645         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8646         rsurface.modelelement3i = (int *)element3i;
8647         rsurface.modelelement3i_indexbuffer = NULL;
8648         rsurface.modelelement3i_bufferoffset = 0;
8649         rsurface.modelelement3s = (unsigned short *)element3s;
8650         rsurface.modelelement3s_indexbuffer = NULL;
8651         rsurface.modelelement3s_bufferoffset = 0;
8652         rsurface.modellightmapoffsets = NULL;
8653         rsurface.modelsurfaces = NULL;
8654         rsurface.batchgeneratedvertex = false;
8655         rsurface.batchfirstvertex = 0;
8656         rsurface.batchnumvertices = 0;
8657         rsurface.batchfirsttriangle = 0;
8658         rsurface.batchnumtriangles = 0;
8659         rsurface.batchvertex3f  = NULL;
8660         rsurface.batchvertex3f_vertexbuffer = NULL;
8661         rsurface.batchvertex3f_bufferoffset = 0;
8662         rsurface.batchsvector3f = NULL;
8663         rsurface.batchsvector3f_vertexbuffer = NULL;
8664         rsurface.batchsvector3f_bufferoffset = 0;
8665         rsurface.batchtvector3f = NULL;
8666         rsurface.batchtvector3f_vertexbuffer = NULL;
8667         rsurface.batchtvector3f_bufferoffset = 0;
8668         rsurface.batchnormal3f  = NULL;
8669         rsurface.batchnormal3f_vertexbuffer = NULL;
8670         rsurface.batchnormal3f_bufferoffset = 0;
8671         rsurface.batchlightmapcolor4f = NULL;
8672         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8673         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8674         rsurface.batchtexcoordtexture2f = NULL;
8675         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8676         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8677         rsurface.batchtexcoordlightmap2f = NULL;
8678         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8679         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8680         rsurface.batchskeletalindex4ub = NULL;
8681         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8682         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8683         rsurface.batchskeletalweight4ub = NULL;
8684         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8685         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8686         rsurface.batchvertexmesh = NULL;
8687         rsurface.batchvertexmesh_vertexbuffer = NULL;
8688         rsurface.batchvertexmesh_bufferoffset = 0;
8689         rsurface.batchelement3i = NULL;
8690         rsurface.batchelement3i_indexbuffer = NULL;
8691         rsurface.batchelement3i_bufferoffset = 0;
8692         rsurface.batchelement3s = NULL;
8693         rsurface.batchelement3s_indexbuffer = NULL;
8694         rsurface.batchelement3s_bufferoffset = 0;
8695         rsurface.passcolor4f = NULL;
8696         rsurface.passcolor4f_vertexbuffer = NULL;
8697         rsurface.passcolor4f_bufferoffset = 0;
8698         rsurface.forcecurrenttextureupdate = true;
8699
8700         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8701         {
8702                 if ((wantnormals || wanttangents) && !normal3f)
8703                 {
8704                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8705                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8706                 }
8707                 if (wanttangents && !svector3f)
8708                 {
8709                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8710                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8711                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8712                 }
8713         }
8714 }
8715
8716 float RSurf_FogPoint(const float *v)
8717 {
8718         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8719         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8720         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8721         float FogHeightFade = r_refdef.fogheightfade;
8722         float fogfrac;
8723         unsigned int fogmasktableindex;
8724         if (r_refdef.fogplaneviewabove)
8725                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8726         else
8727                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8728         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8729         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8730 }
8731
8732 float RSurf_FogVertex(const float *v)
8733 {
8734         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8735         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8736         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8737         float FogHeightFade = rsurface.fogheightfade;
8738         float fogfrac;
8739         unsigned int fogmasktableindex;
8740         if (r_refdef.fogplaneviewabove)
8741                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8742         else
8743                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8744         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8745         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8746 }
8747
8748 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8749 {
8750         int i;
8751         for (i = 0;i < numelements;i++)
8752                 outelement3i[i] = inelement3i[i] + adjust;
8753 }
8754
8755 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8756 extern cvar_t gl_vbo;
8757 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8758 {
8759         int deformindex;
8760         int firsttriangle;
8761         int numtriangles;
8762         int firstvertex;
8763         int endvertex;
8764         int numvertices;
8765         int surfacefirsttriangle;
8766         int surfacenumtriangles;
8767         int surfacefirstvertex;
8768         int surfaceendvertex;
8769         int surfacenumvertices;
8770         int batchnumsurfaces = texturenumsurfaces;
8771         int batchnumvertices;
8772         int batchnumtriangles;
8773         int needsupdate;
8774         int i, j;
8775         qboolean gaps;
8776         qboolean dynamicvertex;
8777         float amplitude;
8778         float animpos;
8779         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8780         float waveparms[4];
8781         unsigned char *ub;
8782         q3shaderinfo_deform_t *deform;
8783         const msurface_t *surface, *firstsurface;
8784         r_vertexmesh_t *vertexmesh;
8785         if (!texturenumsurfaces)
8786                 return;
8787         // find vertex range of this surface batch
8788         gaps = false;
8789         firstsurface = texturesurfacelist[0];
8790         firsttriangle = firstsurface->num_firsttriangle;
8791         batchnumvertices = 0;
8792         batchnumtriangles = 0;
8793         firstvertex = endvertex = firstsurface->num_firstvertex;
8794         for (i = 0;i < texturenumsurfaces;i++)
8795         {
8796                 surface = texturesurfacelist[i];
8797                 if (surface != firstsurface + i)
8798                         gaps = true;
8799                 surfacefirstvertex = surface->num_firstvertex;
8800                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8801                 surfacenumvertices = surface->num_vertices;
8802                 surfacenumtriangles = surface->num_triangles;
8803                 if (firstvertex > surfacefirstvertex)
8804                         firstvertex = surfacefirstvertex;
8805                 if (endvertex < surfaceendvertex)
8806                         endvertex = surfaceendvertex;
8807                 batchnumvertices += surfacenumvertices;
8808                 batchnumtriangles += surfacenumtriangles;
8809         }
8810
8811         r_refdef.stats[r_stat_batch_batches]++;
8812         if (gaps)
8813                 r_refdef.stats[r_stat_batch_withgaps]++;
8814         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8815         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8816         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8817
8818         // we now know the vertex range used, and if there are any gaps in it
8819         rsurface.batchfirstvertex = firstvertex;
8820         rsurface.batchnumvertices = endvertex - firstvertex;
8821         rsurface.batchfirsttriangle = firsttriangle;
8822         rsurface.batchnumtriangles = batchnumtriangles;
8823
8824         // this variable holds flags for which properties have been updated that
8825         // may require regenerating vertexmesh array...
8826         needsupdate = 0;
8827
8828         // check if any dynamic vertex processing must occur
8829         dynamicvertex = false;
8830
8831         // a cvar to force the dynamic vertex path to be taken, for debugging
8832         if (r_batch_debugdynamicvertexpath.integer)
8833         {
8834                 if (!dynamicvertex)
8835                 {
8836                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8837                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8838                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8839                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8840                 }
8841                 dynamicvertex = true;
8842         }
8843
8844         // if there is a chance of animated vertex colors, it's a dynamic batch
8845         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8846         {
8847                 if (!dynamicvertex)
8848                 {
8849                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8850                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8851                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8852                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8853                 }
8854                 dynamicvertex = true;
8855                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8856         }
8857
8858         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8859         {
8860                 switch (deform->deform)
8861                 {
8862                 default:
8863                 case Q3DEFORM_PROJECTIONSHADOW:
8864                 case Q3DEFORM_TEXT0:
8865                 case Q3DEFORM_TEXT1:
8866                 case Q3DEFORM_TEXT2:
8867                 case Q3DEFORM_TEXT3:
8868                 case Q3DEFORM_TEXT4:
8869                 case Q3DEFORM_TEXT5:
8870                 case Q3DEFORM_TEXT6:
8871                 case Q3DEFORM_TEXT7:
8872                 case Q3DEFORM_NONE:
8873                         break;
8874                 case Q3DEFORM_AUTOSPRITE:
8875                         if (!dynamicvertex)
8876                         {
8877                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8878                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8879                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8880                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8881                         }
8882                         dynamicvertex = true;
8883                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8884                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8885                         break;
8886                 case Q3DEFORM_AUTOSPRITE2:
8887                         if (!dynamicvertex)
8888                         {
8889                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8890                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8891                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8892                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8893                         }
8894                         dynamicvertex = true;
8895                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8896                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8897                         break;
8898                 case Q3DEFORM_NORMAL:
8899                         if (!dynamicvertex)
8900                         {
8901                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8902                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8903                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8904                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8905                         }
8906                         dynamicvertex = true;
8907                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8908                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8909                         break;
8910                 case Q3DEFORM_WAVE:
8911                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8912                                 break; // if wavefunc is a nop, ignore this transform
8913                         if (!dynamicvertex)
8914                         {
8915                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8916                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8917                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8918                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8919                         }
8920                         dynamicvertex = true;
8921                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8922                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8923                         break;
8924                 case Q3DEFORM_BULGE:
8925                         if (!dynamicvertex)
8926                         {
8927                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8928                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8929                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8930                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8931                         }
8932                         dynamicvertex = true;
8933                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8934                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8935                         break;
8936                 case Q3DEFORM_MOVE:
8937                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8938                                 break; // if wavefunc is a nop, ignore this transform
8939                         if (!dynamicvertex)
8940                         {
8941                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8942                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8943                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8944                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8945                         }
8946                         dynamicvertex = true;
8947                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8948                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8949                         break;
8950                 }
8951         }
8952         if (rsurface.texture->materialshaderpass)
8953         {
8954                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8955                 {
8956                 default:
8957                 case Q3TCGEN_TEXTURE:
8958                         break;
8959                 case Q3TCGEN_LIGHTMAP:
8960                         if (!dynamicvertex)
8961                         {
8962                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8963                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8964                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8965                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8966                         }
8967                         dynamicvertex = true;
8968                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8969                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8970                         break;
8971                 case Q3TCGEN_VECTOR:
8972                         if (!dynamicvertex)
8973                         {
8974                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8975                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8976                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8977                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8978                         }
8979                         dynamicvertex = true;
8980                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8981                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8982                         break;
8983                 case Q3TCGEN_ENVIRONMENT:
8984                         if (!dynamicvertex)
8985                         {
8986                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8987                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
8988                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
8989                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
8990                         }
8991                         dynamicvertex = true;
8992                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8993                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8994                         break;
8995                 }
8996                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8997                 {
8998                         if (!dynamicvertex)
8999                         {
9000                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9001                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9002                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9003                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9004                         }
9005                         dynamicvertex = true;
9006                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9007                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9008                 }
9009         }
9010
9011         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9012         {
9013                 if (!dynamicvertex)
9014                 {
9015                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9016                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9017                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9018                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9019                 }
9020                 dynamicvertex = true;
9021                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9022         }
9023
9024         // when the model data has no vertex buffer (dynamic mesh), we need to
9025         // eliminate gaps
9026         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9027                 batchneed |= BATCHNEED_NOGAPS;
9028
9029         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9030         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9031         // we ensure this by treating the vertex batch as dynamic...
9032         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9033         {
9034                 if (!dynamicvertex)
9035                 {
9036                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9037                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9038                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9039                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9040                 }
9041                 dynamicvertex = true;
9042         }
9043
9044         if (dynamicvertex)
9045         {
9046                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9047                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9048                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9049                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9050                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9051                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9052                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9053                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9054         }
9055
9056         // if needsupdate, we have to do a dynamic vertex batch for sure
9057         if (needsupdate & batchneed)
9058         {
9059                 if (!dynamicvertex)
9060                 {
9061                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9062                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9063                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9064                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9065                 }
9066                 dynamicvertex = true;
9067         }
9068
9069         // see if we need to build vertexmesh from arrays
9070         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9071         {
9072                 if (!dynamicvertex)
9073                 {
9074                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9075                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9076                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9077                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9078                 }
9079                 dynamicvertex = true;
9080         }
9081
9082         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9083         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9084                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9085
9086         rsurface.batchvertex3f = rsurface.modelvertex3f;
9087         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9088         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9089         rsurface.batchsvector3f = rsurface.modelsvector3f;
9090         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9091         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9092         rsurface.batchtvector3f = rsurface.modeltvector3f;
9093         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9094         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9095         rsurface.batchnormal3f = rsurface.modelnormal3f;
9096         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9097         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9098         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9099         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9100         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9101         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9102         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9103         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9104         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9105         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9106         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9107         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9108         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9109         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9110         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9111         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9112         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9113         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9114         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9115         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9116         rsurface.batchelement3i = rsurface.modelelement3i;
9117         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9118         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9119         rsurface.batchelement3s = rsurface.modelelement3s;
9120         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9121         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9122         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9123         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9124         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9125         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9126         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9127
9128         // if any dynamic vertex processing has to occur in software, we copy the
9129         // entire surface list together before processing to rebase the vertices
9130         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9131         //
9132         // if any gaps exist and we do not have a static vertex buffer, we have to
9133         // copy the surface list together to avoid wasting upload bandwidth on the
9134         // vertices in the gaps.
9135         //
9136         // if gaps exist and we have a static vertex buffer, we can choose whether
9137         // to combine the index buffer ranges into one dynamic index buffer or
9138         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9139         //
9140         // in many cases the batch is reduced to one draw call.
9141
9142         rsurface.batchmultidraw = false;
9143         rsurface.batchmultidrawnumsurfaces = 0;
9144         rsurface.batchmultidrawsurfacelist = NULL;
9145
9146         if (!dynamicvertex)
9147         {
9148                 // static vertex data, just set pointers...
9149                 rsurface.batchgeneratedvertex = false;
9150                 // if there are gaps, we want to build a combined index buffer,
9151                 // otherwise use the original static buffer with an appropriate offset
9152                 if (gaps)
9153                 {
9154                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9155                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9156                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9157                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9158                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9159                         {
9160                                 rsurface.batchmultidraw = true;
9161                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9162                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9163                                 return;
9164                         }
9165                         // build a new triangle elements array for this batch
9166                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9167                         rsurface.batchfirsttriangle = 0;
9168                         numtriangles = 0;
9169                         for (i = 0;i < texturenumsurfaces;i++)
9170                         {
9171                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9172                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9173                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9174                                 numtriangles += surfacenumtriangles;
9175                         }
9176                         rsurface.batchelement3i_indexbuffer = NULL;
9177                         rsurface.batchelement3i_bufferoffset = 0;
9178                         rsurface.batchelement3s = NULL;
9179                         rsurface.batchelement3s_indexbuffer = NULL;
9180                         rsurface.batchelement3s_bufferoffset = 0;
9181                         if (endvertex <= 65536)
9182                         {
9183                                 // make a 16bit (unsigned short) index array if possible
9184                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9185                                 for (i = 0;i < numtriangles*3;i++)
9186                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9187                         }
9188                         // upload buffer data for the copytriangles batch
9189                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9190                         {
9191                                 if (rsurface.batchelement3s)
9192                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9193                                 else if (rsurface.batchelement3i)
9194                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9195                         }
9196                 }
9197                 else
9198                 {
9199                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9200                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9201                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9202                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9203                 }
9204                 return;
9205         }
9206
9207         // something needs software processing, do it for real...
9208         // we only directly handle separate array data in this case and then
9209         // generate interleaved data if needed...
9210         rsurface.batchgeneratedvertex = true;
9211         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9212         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9213         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9214         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9215
9216         // now copy the vertex data into a combined array and make an index array
9217         // (this is what Quake3 does all the time)
9218         // we also apply any skeletal animation here that would have been done in
9219         // the vertex shader, because most of the dynamic vertex animation cases
9220         // need actual vertex positions and normals
9221         //if (dynamicvertex)
9222         {
9223                 rsurface.batchvertexmesh = NULL;
9224                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9225                 rsurface.batchvertexmesh_bufferoffset = 0;
9226                 rsurface.batchvertex3f = NULL;
9227                 rsurface.batchvertex3f_vertexbuffer = NULL;
9228                 rsurface.batchvertex3f_bufferoffset = 0;
9229                 rsurface.batchsvector3f = NULL;
9230                 rsurface.batchsvector3f_vertexbuffer = NULL;
9231                 rsurface.batchsvector3f_bufferoffset = 0;
9232                 rsurface.batchtvector3f = NULL;
9233                 rsurface.batchtvector3f_vertexbuffer = NULL;
9234                 rsurface.batchtvector3f_bufferoffset = 0;
9235                 rsurface.batchnormal3f = NULL;
9236                 rsurface.batchnormal3f_vertexbuffer = NULL;
9237                 rsurface.batchnormal3f_bufferoffset = 0;
9238                 rsurface.batchlightmapcolor4f = NULL;
9239                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9240                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9241                 rsurface.batchtexcoordtexture2f = NULL;
9242                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9243                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9244                 rsurface.batchtexcoordlightmap2f = NULL;
9245                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9246                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9247                 rsurface.batchskeletalindex4ub = NULL;
9248                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9249                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9250                 rsurface.batchskeletalweight4ub = NULL;
9251                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9252                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9253                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9254                 rsurface.batchelement3i_indexbuffer = NULL;
9255                 rsurface.batchelement3i_bufferoffset = 0;
9256                 rsurface.batchelement3s = NULL;
9257                 rsurface.batchelement3s_indexbuffer = NULL;
9258                 rsurface.batchelement3s_bufferoffset = 0;
9259                 rsurface.batchskeletaltransform3x4buffer = NULL;
9260                 rsurface.batchskeletaltransform3x4offset = 0;
9261                 rsurface.batchskeletaltransform3x4size = 0;
9262                 // we'll only be setting up certain arrays as needed
9263                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9264                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9265                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9266                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9267                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9268                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9269                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9270                 {
9271                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9272                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9273                 }
9274                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9275                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9276                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9277                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9278                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9279                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9280                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9281                 {
9282                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9283                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9284                 }
9285                 numvertices = 0;
9286                 numtriangles = 0;
9287                 for (i = 0;i < texturenumsurfaces;i++)
9288                 {
9289                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9290                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9291                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9292                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9293                         // copy only the data requested
9294                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9295                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9296                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9297                         {
9298                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9299                                 {
9300                                         if (rsurface.batchvertex3f)
9301                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9302                                         else
9303                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9304                                 }
9305                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9306                                 {
9307                                         if (rsurface.modelnormal3f)
9308                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9309                                         else
9310                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9311                                 }
9312                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9313                                 {
9314                                         if (rsurface.modelsvector3f)
9315                                         {
9316                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9317                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9318                                         }
9319                                         else
9320                                         {
9321                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9322                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9323                                         }
9324                                 }
9325                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9326                                 {
9327                                         if (rsurface.modellightmapcolor4f)
9328                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9329                                         else
9330                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9331                                 }
9332                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9333                                 {
9334                                         if (rsurface.modeltexcoordtexture2f)
9335                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9336                                         else
9337                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9338                                 }
9339                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9340                                 {
9341                                         if (rsurface.modeltexcoordlightmap2f)
9342                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9343                                         else
9344                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9345                                 }
9346                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9347                                 {
9348                                         if (rsurface.modelskeletalindex4ub)
9349                                         {
9350                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9351                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9352                                         }
9353                                         else
9354                                         {
9355                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9356                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9357                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9358                                                 for (j = 0;j < surfacenumvertices;j++)
9359                                                         ub[j*4] = 255;
9360                                         }
9361                                 }
9362                         }
9363                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9364                         numvertices += surfacenumvertices;
9365                         numtriangles += surfacenumtriangles;
9366                 }
9367
9368                 // generate a 16bit index array as well if possible
9369                 // (in general, dynamic batches fit)
9370                 if (numvertices <= 65536)
9371                 {
9372                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9373                         for (i = 0;i < numtriangles*3;i++)
9374                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9375                 }
9376
9377                 // since we've copied everything, the batch now starts at 0
9378                 rsurface.batchfirstvertex = 0;
9379                 rsurface.batchnumvertices = batchnumvertices;
9380                 rsurface.batchfirsttriangle = 0;
9381                 rsurface.batchnumtriangles = batchnumtriangles;
9382         }
9383
9384         // apply skeletal animation that would have been done in the vertex shader
9385         if (rsurface.batchskeletaltransform3x4)
9386         {
9387                 const unsigned char *si;
9388                 const unsigned char *sw;
9389                 const float *t[4];
9390                 const float *b = rsurface.batchskeletaltransform3x4;
9391                 float *vp, *vs, *vt, *vn;
9392                 float w[4];
9393                 float m[3][4], n[3][4];
9394                 float tp[3], ts[3], tt[3], tn[3];
9395                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9396                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9397                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9398                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9399                 si = rsurface.batchskeletalindex4ub;
9400                 sw = rsurface.batchskeletalweight4ub;
9401                 vp = rsurface.batchvertex3f;
9402                 vs = rsurface.batchsvector3f;
9403                 vt = rsurface.batchtvector3f;
9404                 vn = rsurface.batchnormal3f;
9405                 memset(m[0], 0, sizeof(m));
9406                 memset(n[0], 0, sizeof(n));
9407                 for (i = 0;i < batchnumvertices;i++)
9408                 {
9409                         t[0] = b + si[0]*12;
9410                         if (sw[0] == 255)
9411                         {
9412                                 // common case - only one matrix
9413                                 m[0][0] = t[0][ 0];
9414                                 m[0][1] = t[0][ 1];
9415                                 m[0][2] = t[0][ 2];
9416                                 m[0][3] = t[0][ 3];
9417                                 m[1][0] = t[0][ 4];
9418                                 m[1][1] = t[0][ 5];
9419                                 m[1][2] = t[0][ 6];
9420                                 m[1][3] = t[0][ 7];
9421                                 m[2][0] = t[0][ 8];
9422                                 m[2][1] = t[0][ 9];
9423                                 m[2][2] = t[0][10];
9424                                 m[2][3] = t[0][11];
9425                         }
9426                         else if (sw[2] + sw[3])
9427                         {
9428                                 // blend 4 matrices
9429                                 t[1] = b + si[1]*12;
9430                                 t[2] = b + si[2]*12;
9431                                 t[3] = b + si[3]*12;
9432                                 w[0] = sw[0] * (1.0f / 255.0f);
9433                                 w[1] = sw[1] * (1.0f / 255.0f);
9434                                 w[2] = sw[2] * (1.0f / 255.0f);
9435                                 w[3] = sw[3] * (1.0f / 255.0f);
9436                                 // blend the matrices
9437                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9438                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9439                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9440                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9441                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9442                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9443                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9444                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9445                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9446                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9447                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9448                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9449                         }
9450                         else
9451                         {
9452                                 // blend 2 matrices
9453                                 t[1] = b + si[1]*12;
9454                                 w[0] = sw[0] * (1.0f / 255.0f);
9455                                 w[1] = sw[1] * (1.0f / 255.0f);
9456                                 // blend the matrices
9457                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9458                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9459                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9460                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9461                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9462                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9463                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9464                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9465                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9466                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9467                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9468                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9469                         }
9470                         si += 4;
9471                         sw += 4;
9472                         // modify the vertex
9473                         VectorCopy(vp, tp);
9474                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9475                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9476                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9477                         vp += 3;
9478                         if (vn)
9479                         {
9480                                 // the normal transformation matrix is a set of cross products...
9481                                 CrossProduct(m[1], m[2], n[0]);
9482                                 CrossProduct(m[2], m[0], n[1]);
9483                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9484                                 VectorCopy(vn, tn);
9485                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9486                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9487                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9488                                 VectorNormalize(vn);
9489                                 vn += 3;
9490                                 if (vs)
9491                                 {
9492                                         VectorCopy(vs, ts);
9493                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9494                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9495                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9496                                         VectorNormalize(vs);
9497                                         vs += 3;
9498                                         VectorCopy(vt, tt);
9499                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9500                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9501                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9502                                         VectorNormalize(vt);
9503                                         vt += 3;
9504                                 }
9505                         }
9506                 }
9507                 rsurface.batchskeletaltransform3x4 = NULL;
9508                 rsurface.batchskeletalnumtransforms = 0;
9509         }
9510
9511         // q1bsp surfaces rendered in vertex color mode have to have colors
9512         // calculated based on lightstyles
9513         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9514         {
9515                 // generate color arrays for the surfaces in this list
9516                 int c[4];
9517                 int scale;
9518                 int size3;
9519                 const int *offsets;
9520                 const unsigned char *lm;
9521                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9522                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9523                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9524                 numvertices = 0;
9525                 for (i = 0;i < texturenumsurfaces;i++)
9526                 {
9527                         surface = texturesurfacelist[i];
9528                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9529                         surfacenumvertices = surface->num_vertices;
9530                         if (surface->lightmapinfo->samples)
9531                         {
9532                                 for (j = 0;j < surfacenumvertices;j++)
9533                                 {
9534                                         lm = surface->lightmapinfo->samples + offsets[j];
9535                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9536                                         VectorScale(lm, scale, c);
9537                                         if (surface->lightmapinfo->styles[1] != 255)
9538                                         {
9539                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9540                                                 lm += size3;
9541                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9542                                                 VectorMA(c, scale, lm, c);
9543                                                 if (surface->lightmapinfo->styles[2] != 255)
9544                                                 {
9545                                                         lm += size3;
9546                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9547                                                         VectorMA(c, scale, lm, c);
9548                                                         if (surface->lightmapinfo->styles[3] != 255)
9549                                                         {
9550                                                                 lm += size3;
9551                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9552                                                                 VectorMA(c, scale, lm, c);
9553                                                         }
9554                                                 }
9555                                         }
9556                                         c[0] >>= 7;
9557                                         c[1] >>= 7;
9558                                         c[2] >>= 7;
9559                                         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);
9560                                         numvertices++;
9561                                 }
9562                         }
9563                         else
9564                         {
9565                                 for (j = 0;j < surfacenumvertices;j++)
9566                                 {
9567                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9568                                         numvertices++;
9569                                 }
9570                         }
9571                 }
9572         }
9573
9574         // if vertices are deformed (sprite flares and things in maps, possibly
9575         // water waves, bulges and other deformations), modify the copied vertices
9576         // in place
9577         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9578         {
9579                 float scale;
9580                 switch (deform->deform)
9581                 {
9582                 default:
9583                 case Q3DEFORM_PROJECTIONSHADOW:
9584                 case Q3DEFORM_TEXT0:
9585                 case Q3DEFORM_TEXT1:
9586                 case Q3DEFORM_TEXT2:
9587                 case Q3DEFORM_TEXT3:
9588                 case Q3DEFORM_TEXT4:
9589                 case Q3DEFORM_TEXT5:
9590                 case Q3DEFORM_TEXT6:
9591                 case Q3DEFORM_TEXT7:
9592                 case Q3DEFORM_NONE:
9593                         break;
9594                 case Q3DEFORM_AUTOSPRITE:
9595                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9596                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9597                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9598                         VectorNormalize(newforward);
9599                         VectorNormalize(newright);
9600                         VectorNormalize(newup);
9601 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9602 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9603 //                      rsurface.batchvertex3f_bufferoffset = 0;
9604 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9605 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9606 //                      rsurface.batchsvector3f_bufferoffset = 0;
9607 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9608 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9609 //                      rsurface.batchtvector3f_bufferoffset = 0;
9610 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9611 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9612 //                      rsurface.batchnormal3f_bufferoffset = 0;
9613                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9614                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9615                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9616                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9617                                 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);
9618                         // a single autosprite surface can contain multiple sprites...
9619                         for (j = 0;j < batchnumvertices - 3;j += 4)
9620                         {
9621                                 VectorClear(center);
9622                                 for (i = 0;i < 4;i++)
9623                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9624                                 VectorScale(center, 0.25f, center);
9625                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9626                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9627                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9628                                 for (i = 0;i < 4;i++)
9629                                 {
9630                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9631                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9632                                 }
9633                         }
9634                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9635                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9636                         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);
9637                         break;
9638                 case Q3DEFORM_AUTOSPRITE2:
9639                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9640                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9641                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9642                         VectorNormalize(newforward);
9643                         VectorNormalize(newright);
9644                         VectorNormalize(newup);
9645 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9646 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9647 //                      rsurface.batchvertex3f_bufferoffset = 0;
9648                         {
9649                                 const float *v1, *v2;
9650                                 vec3_t start, end;
9651                                 float f, l;
9652                                 struct
9653                                 {
9654                                         float length2;
9655                                         const float *v1;
9656                                         const float *v2;
9657                                 }
9658                                 shortest[2];
9659                                 memset(shortest, 0, sizeof(shortest));
9660                                 // a single autosprite surface can contain multiple sprites...
9661                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9662                                 {
9663                                         VectorClear(center);
9664                                         for (i = 0;i < 4;i++)
9665                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9666                                         VectorScale(center, 0.25f, center);
9667                                         // find the two shortest edges, then use them to define the
9668                                         // axis vectors for rotating around the central axis
9669                                         for (i = 0;i < 6;i++)
9670                                         {
9671                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9672                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9673                                                 l = VectorDistance2(v1, v2);
9674                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9675                                                 if (v1[2] != v2[2])
9676                                                         l += (1.0f / 1024.0f);
9677                                                 if (shortest[0].length2 > l || i == 0)
9678                                                 {
9679                                                         shortest[1] = shortest[0];
9680                                                         shortest[0].length2 = l;
9681                                                         shortest[0].v1 = v1;
9682                                                         shortest[0].v2 = v2;
9683                                                 }
9684                                                 else if (shortest[1].length2 > l || i == 1)
9685                                                 {
9686                                                         shortest[1].length2 = l;
9687                                                         shortest[1].v1 = v1;
9688                                                         shortest[1].v2 = v2;
9689                                                 }
9690                                         }
9691                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9692                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9693                                         // this calculates the right vector from the shortest edge
9694                                         // and the up vector from the edge midpoints
9695                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9696                                         VectorNormalize(right);
9697                                         VectorSubtract(end, start, up);
9698                                         VectorNormalize(up);
9699                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9700                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9701                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9702                                         VectorNegate(forward, forward);
9703                                         VectorReflect(forward, 0, up, forward);
9704                                         VectorNormalize(forward);
9705                                         CrossProduct(up, forward, newright);
9706                                         VectorNormalize(newright);
9707                                         // rotate the quad around the up axis vector, this is made
9708                                         // especially easy by the fact we know the quad is flat,
9709                                         // so we only have to subtract the center position and
9710                                         // measure distance along the right vector, and then
9711                                         // multiply that by the newright vector and add back the
9712                                         // center position
9713                                         // we also need to subtract the old position to undo the
9714                                         // displacement from the center, which we do with a
9715                                         // DotProduct, the subtraction/addition of center is also
9716                                         // optimized into DotProducts here
9717                                         l = DotProduct(right, center);
9718                                         for (i = 0;i < 4;i++)
9719                                         {
9720                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9721                                                 f = DotProduct(right, v1) - l;
9722                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9723                                         }
9724                                 }
9725                         }
9726                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9727                         {
9728 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9729 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9730 //                              rsurface.batchnormal3f_bufferoffset = 0;
9731                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9732                         }
9733                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9734                         {
9735 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9736 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9737 //                              rsurface.batchsvector3f_bufferoffset = 0;
9738 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9739 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9740 //                              rsurface.batchtvector3f_bufferoffset = 0;
9741                                 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);
9742                         }
9743                         break;
9744                 case Q3DEFORM_NORMAL:
9745                         // deform the normals to make reflections wavey
9746                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9747                         rsurface.batchnormal3f_vertexbuffer = NULL;
9748                         rsurface.batchnormal3f_bufferoffset = 0;
9749                         for (j = 0;j < batchnumvertices;j++)
9750                         {
9751                                 float vertex[3];
9752                                 float *normal = rsurface.batchnormal3f + 3*j;
9753                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9754                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9755                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9756                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9757                                 VectorNormalize(normal);
9758                         }
9759                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9760                         {
9761 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9762 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9763 //                              rsurface.batchsvector3f_bufferoffset = 0;
9764 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9765 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9766 //                              rsurface.batchtvector3f_bufferoffset = 0;
9767                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9768                         }
9769                         break;
9770                 case Q3DEFORM_WAVE:
9771                         // deform vertex array to make wavey water and flags and such
9772                         waveparms[0] = deform->waveparms[0];
9773                         waveparms[1] = deform->waveparms[1];
9774                         waveparms[2] = deform->waveparms[2];
9775                         waveparms[3] = deform->waveparms[3];
9776                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9777                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9778                         // this is how a divisor of vertex influence on deformation
9779                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9780                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9781 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9782 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9783 //                      rsurface.batchvertex3f_bufferoffset = 0;
9784 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9785 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9786 //                      rsurface.batchnormal3f_bufferoffset = 0;
9787                         for (j = 0;j < batchnumvertices;j++)
9788                         {
9789                                 // if the wavefunc depends on time, evaluate it per-vertex
9790                                 if (waveparms[3])
9791                                 {
9792                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9793                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9794                                 }
9795                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9796                         }
9797                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9798                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9799                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9800                         {
9801 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9802 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9803 //                              rsurface.batchsvector3f_bufferoffset = 0;
9804 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9805 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9806 //                              rsurface.batchtvector3f_bufferoffset = 0;
9807                                 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);
9808                         }
9809                         break;
9810                 case Q3DEFORM_BULGE:
9811                         // deform vertex array to make the surface have moving bulges
9812 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9813 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9814 //                      rsurface.batchvertex3f_bufferoffset = 0;
9815 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9816 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9817 //                      rsurface.batchnormal3f_bufferoffset = 0;
9818                         for (j = 0;j < batchnumvertices;j++)
9819                         {
9820                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9821                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9822                         }
9823                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9824                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9825                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9826                         {
9827 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9828 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9829 //                              rsurface.batchsvector3f_bufferoffset = 0;
9830 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9831 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9832 //                              rsurface.batchtvector3f_bufferoffset = 0;
9833                                 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);
9834                         }
9835                         break;
9836                 case Q3DEFORM_MOVE:
9837                         // deform vertex array
9838                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9839                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9840                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9841                         VectorScale(deform->parms, scale, waveparms);
9842 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9843 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9844 //                      rsurface.batchvertex3f_bufferoffset = 0;
9845                         for (j = 0;j < batchnumvertices;j++)
9846                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9847                         break;
9848                 }
9849         }
9850
9851         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9852         {
9853         // generate texcoords based on the chosen texcoord source
9854                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9855                 {
9856                 default:
9857                 case Q3TCGEN_TEXTURE:
9858                         break;
9859                 case Q3TCGEN_LIGHTMAP:
9860         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9861         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9862         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9863                         if (rsurface.batchtexcoordlightmap2f)
9864                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9865                         break;
9866                 case Q3TCGEN_VECTOR:
9867         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9868         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9869         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9870                         for (j = 0;j < batchnumvertices;j++)
9871                         {
9872                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9873                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9874                         }
9875                         break;
9876                 case Q3TCGEN_ENVIRONMENT:
9877                         // make environment reflections using a spheremap
9878                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9879                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9880                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9881                         for (j = 0;j < batchnumvertices;j++)
9882                         {
9883                                 // identical to Q3A's method, but executed in worldspace so
9884                                 // carried models can be shiny too
9885
9886                                 float viewer[3], d, reflected[3], worldreflected[3];
9887
9888                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9889                                 // VectorNormalize(viewer);
9890
9891                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9892
9893                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9894                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9895                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9896                                 // note: this is proportinal to viewer, so we can normalize later
9897
9898                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9899                                 VectorNormalize(worldreflected);
9900
9901                                 // note: this sphere map only uses world x and z!
9902                                 // so positive and negative y will LOOK THE SAME.
9903                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9904                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9905                         }
9906                         break;
9907                 }
9908                 // the only tcmod that needs software vertex processing is turbulent, so
9909                 // check for it here and apply the changes if needed
9910                 // and we only support that as the first one
9911                 // (handling a mixture of turbulent and other tcmods would be problematic
9912                 //  without punting it entirely to a software path)
9913                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9914                 {
9915                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9916                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9917         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9918         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9919         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9920                         for (j = 0;j < batchnumvertices;j++)
9921                         {
9922                                 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);
9923                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9924                         }
9925                 }
9926         }
9927
9928         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9929         {
9930                 // convert the modified arrays to vertex structs
9931 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9932 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
9933 //              rsurface.batchvertexmesh_bufferoffset = 0;
9934                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9935                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9936                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9937                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9938                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9939                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9940                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9941                 {
9942                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9943                         {
9944                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9945                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9946                         }
9947                 }
9948                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9949                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9950                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9951                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9952                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9953                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9954                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9955                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9956                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9957                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9958                 {
9959                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9960                         {
9961                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9962                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9963                         }
9964                 }
9965         }
9966
9967         // upload buffer data for the dynamic batch
9968         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9969         {
9970                 if (rsurface.batchvertexmesh)
9971                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
9972                 else
9973                 {
9974                         if (rsurface.batchvertex3f)
9975                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
9976                         if (rsurface.batchsvector3f)
9977                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
9978                         if (rsurface.batchtvector3f)
9979                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
9980                         if (rsurface.batchnormal3f)
9981                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
9982                         if (rsurface.batchlightmapcolor4f)
9983                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
9984                         if (rsurface.batchtexcoordtexture2f)
9985                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
9986                         if (rsurface.batchtexcoordlightmap2f)
9987                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
9988                         if (rsurface.batchskeletalindex4ub)
9989                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
9990                         if (rsurface.batchskeletalweight4ub)
9991                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
9992                 }
9993                 if (rsurface.batchelement3s)
9994                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9995                 else if (rsurface.batchelement3i)
9996                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9997         }
9998 }
9999
10000 void RSurf_DrawBatch(void)
10001 {
10002         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10003         // through the pipeline, killing it earlier in the pipeline would have
10004         // per-surface overhead rather than per-batch overhead, so it's best to
10005         // reject it here, before it hits glDraw.
10006         if (rsurface.batchnumtriangles == 0)
10007                 return;
10008 #if 0
10009         // batch debugging code
10010         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10011         {
10012                 int i;
10013                 int j;
10014                 int c;
10015                 const int *e;
10016                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10017                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10018                 {
10019                         c = e[i];
10020                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10021                         {
10022                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10023                                 {
10024                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10025                                                 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);
10026                                         break;
10027                                 }
10028                         }
10029                 }
10030         }
10031 #endif
10032         if (rsurface.batchmultidraw)
10033         {
10034                 // issue multiple draws rather than copying index data
10035                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10036                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10037                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10038                 for (i = 0;i < numsurfaces;)
10039                 {
10040                         // combine consecutive surfaces as one draw
10041                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10042                                 if (surfacelist[j] != surfacelist[k] + 1)
10043                                         break;
10044                         firstvertex = surfacelist[i]->num_firstvertex;
10045                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10046                         firsttriangle = surfacelist[i]->num_firsttriangle;
10047                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10048                         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);
10049                         i = j;
10050                 }
10051         }
10052         else
10053         {
10054                 // there is only one consecutive run of index data (may have been combined)
10055                 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);
10056         }
10057 }
10058
10059 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10060 {
10061         // pick the closest matching water plane
10062         int planeindex, vertexindex, bestplaneindex = -1;
10063         float d, bestd;
10064         vec3_t vert;
10065         const float *v;
10066         r_waterstate_waterplane_t *p;
10067         qboolean prepared = false;
10068         bestd = 0;
10069         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10070         {
10071                 if(p->camera_entity != rsurface.texture->camera_entity)
10072                         continue;
10073                 d = 0;
10074                 if(!prepared)
10075                 {
10076                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10077                         prepared = true;
10078                         if(rsurface.batchnumvertices == 0)
10079                                 break;
10080                 }
10081                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10082                 {
10083                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10084                         d += fabs(PlaneDiff(vert, &p->plane));
10085                 }
10086                 if (bestd > d || bestplaneindex < 0)
10087                 {
10088                         bestd = d;
10089                         bestplaneindex = planeindex;
10090                 }
10091         }
10092         return bestplaneindex;
10093         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10094         // this situation though, as it might be better to render single larger
10095         // batches with useless stuff (backface culled for example) than to
10096         // render multiple smaller batches
10097 }
10098
10099 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10100 {
10101         int i;
10102         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10103         rsurface.passcolor4f_vertexbuffer = 0;
10104         rsurface.passcolor4f_bufferoffset = 0;
10105         for (i = 0;i < rsurface.batchnumvertices;i++)
10106                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10107 }
10108
10109 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10110 {
10111         int i;
10112         float f;
10113         const float *v;
10114         const float *c;
10115         float *c2;
10116         if (rsurface.passcolor4f)
10117         {
10118                 // generate color arrays
10119                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10120                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10121                 rsurface.passcolor4f_vertexbuffer = 0;
10122                 rsurface.passcolor4f_bufferoffset = 0;
10123                 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)
10124                 {
10125                         f = RSurf_FogVertex(v);
10126                         c2[0] = c[0] * f;
10127                         c2[1] = c[1] * f;
10128                         c2[2] = c[2] * f;
10129                         c2[3] = c[3];
10130                 }
10131         }
10132         else
10133         {
10134                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10135                 rsurface.passcolor4f_vertexbuffer = 0;
10136                 rsurface.passcolor4f_bufferoffset = 0;
10137                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10138                 {
10139                         f = RSurf_FogVertex(v);
10140                         c2[0] = f;
10141                         c2[1] = f;
10142                         c2[2] = f;
10143                         c2[3] = 1;
10144                 }
10145         }
10146 }
10147
10148 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10149 {
10150         int i;
10151         float f;
10152         const float *v;
10153         const float *c;
10154         float *c2;
10155         if (!rsurface.passcolor4f)
10156                 return;
10157         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10158         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10159         rsurface.passcolor4f_vertexbuffer = 0;
10160         rsurface.passcolor4f_bufferoffset = 0;
10161         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)
10162         {
10163                 f = RSurf_FogVertex(v);
10164                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10165                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10166                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10167                 c2[3] = c[3];
10168         }
10169 }
10170
10171 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10172 {
10173         int i;
10174         const float *c;
10175         float *c2;
10176         if (!rsurface.passcolor4f)
10177                 return;
10178         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10179         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10180         rsurface.passcolor4f_vertexbuffer = 0;
10181         rsurface.passcolor4f_bufferoffset = 0;
10182         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10183         {
10184                 c2[0] = c[0] * r;
10185                 c2[1] = c[1] * g;
10186                 c2[2] = c[2] * b;
10187                 c2[3] = c[3] * a;
10188         }
10189 }
10190
10191 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10192 {
10193         int i;
10194         const float *c;
10195         float *c2;
10196         if (!rsurface.passcolor4f)
10197                 return;
10198         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10199         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10200         rsurface.passcolor4f_vertexbuffer = 0;
10201         rsurface.passcolor4f_bufferoffset = 0;
10202         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10203         {
10204                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10205                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10206                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10207                 c2[3] = c[3];
10208         }
10209 }
10210
10211 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10212 {
10213         // TODO: optimize
10214         rsurface.passcolor4f = NULL;
10215         rsurface.passcolor4f_vertexbuffer = 0;
10216         rsurface.passcolor4f_bufferoffset = 0;
10217         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10218         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10219         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10220         GL_Color(r, g, b, a);
10221         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10222         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10223         R_Mesh_TexMatrix(0, NULL);
10224         RSurf_DrawBatch();
10225 }
10226
10227 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10228 {
10229         // TODO: optimize applyfog && applycolor case
10230         // just apply fog if necessary, and tint the fog color array if necessary
10231         rsurface.passcolor4f = NULL;
10232         rsurface.passcolor4f_vertexbuffer = 0;
10233         rsurface.passcolor4f_bufferoffset = 0;
10234         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10235         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10236         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10237         GL_Color(r, g, b, a);
10238         RSurf_DrawBatch();
10239 }
10240
10241 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10242 {
10243         // TODO: optimize
10244         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10245         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10246         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10247         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10248         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10249         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10250         GL_Color(r, g, b, a);
10251         RSurf_DrawBatch();
10252 }
10253
10254 static void RSurf_DrawBatch_GL11_ClampColor(void)
10255 {
10256         int i;
10257         const float *c1;
10258         float *c2;
10259         if (!rsurface.passcolor4f)
10260                 return;
10261         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10262         {
10263                 c2[0] = bound(0.0f, c1[0], 1.0f);
10264                 c2[1] = bound(0.0f, c1[1], 1.0f);
10265                 c2[2] = bound(0.0f, c1[2], 1.0f);
10266                 c2[3] = bound(0.0f, c1[3], 1.0f);
10267         }
10268 }
10269
10270 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10271 {
10272         int i;
10273         float f;
10274         const float *v;
10275         const float *n;
10276         float *c;
10277         //vec3_t eyedir;
10278
10279         // fake shading
10280         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10281         rsurface.passcolor4f_vertexbuffer = 0;
10282         rsurface.passcolor4f_bufferoffset = 0;
10283         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10284         {
10285                 f = -DotProduct(r_refdef.view.forward, n);
10286                 f = max(0, f);
10287                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10288                 f *= fakelightintensity;
10289                 Vector4Set(c, f, f, f, 1);
10290         }
10291 }
10292
10293 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10294 {
10295         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10296         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10297         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10298         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10299         GL_Color(r, g, b, a);
10300         RSurf_DrawBatch();
10301 }
10302
10303 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10304 {
10305         int i;
10306         float f;
10307         float alpha;
10308         const float *v;
10309         const float *n;
10310         float *c;
10311         vec3_t ambientcolor;
10312         vec3_t diffusecolor;
10313         vec3_t lightdir;
10314         // TODO: optimize
10315         // model lighting
10316         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10317         f = 0.5f * lightmapintensity;
10318         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10319         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10320         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10321         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10322         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10323         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10324         alpha = *a;
10325         if (VectorLength2(diffusecolor) > 0)
10326         {
10327                 // q3-style directional shading
10328                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10329                 rsurface.passcolor4f_vertexbuffer = 0;
10330                 rsurface.passcolor4f_bufferoffset = 0;
10331                 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)
10332                 {
10333                         if ((f = DotProduct(n, lightdir)) > 0)
10334                                 VectorMA(ambientcolor, f, diffusecolor, c);
10335                         else
10336                                 VectorCopy(ambientcolor, c);
10337                         c[3] = alpha;
10338                 }
10339                 *r = 1;
10340                 *g = 1;
10341                 *b = 1;
10342                 *a = 1;
10343                 *applycolor = false;
10344         }
10345         else
10346         {
10347                 *r = ambientcolor[0];
10348                 *g = ambientcolor[1];
10349                 *b = ambientcolor[2];
10350                 rsurface.passcolor4f = NULL;
10351                 rsurface.passcolor4f_vertexbuffer = 0;
10352                 rsurface.passcolor4f_bufferoffset = 0;
10353         }
10354 }
10355
10356 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10357 {
10358         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10359         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10360         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10361         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10362         GL_Color(r, g, b, a);
10363         RSurf_DrawBatch();
10364 }
10365
10366 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10367 {
10368         int i;
10369         float f;
10370         const float *v;
10371         float *c;
10372
10373         // fake shading
10374         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10375         rsurface.passcolor4f_vertexbuffer = 0;
10376         rsurface.passcolor4f_bufferoffset = 0;
10377
10378         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10379         {
10380                 f = 1 - RSurf_FogVertex(v);
10381                 c[0] = r;
10382                 c[1] = g;
10383                 c[2] = b;
10384                 c[3] = f * a;
10385         }
10386 }
10387
10388 void RSurf_SetupDepthAndCulling(void)
10389 {
10390         // submodels are biased to avoid z-fighting with world surfaces that they
10391         // may be exactly overlapping (avoids z-fighting artifacts on certain
10392         // doors and things in Quake maps)
10393         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10394         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10395         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10396         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10397 }
10398
10399 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10400 {
10401         int i, j;
10402         // transparent sky would be ridiculous
10403         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10404                 return;
10405         R_SetupShader_Generic_NoTexture(false, false);
10406         skyrenderlater = true;
10407         RSurf_SetupDepthAndCulling();
10408         GL_DepthMask(true);
10409
10410         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10411         if (r_sky_scissor.integer)
10412         {
10413                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10414                 for (i = 0; i < texturenumsurfaces; i++)
10415                 {
10416                         const msurface_t *surf = texturesurfacelist[i];
10417                         const float *v;
10418                         float p[3];
10419                         float mins[3], maxs[3];
10420                         int scissor[4];
10421                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10422                         {
10423                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10424                                 if (j > 0)
10425                                 {
10426                                         if (mins[0] > p[0]) mins[0] = p[0];
10427                                         if (mins[1] > p[1]) mins[1] = p[1];
10428                                         if (mins[2] > p[2]) mins[2] = p[2];
10429                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10430                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10431                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10432                                 }
10433                                 else
10434                                 {
10435                                         VectorCopy(p, mins);
10436                                         VectorCopy(p, maxs);
10437                                 }
10438                         }
10439                         if (!R_ScissorForBBox(mins, maxs, scissor))
10440                         {
10441                                 if (skyscissor[2])
10442                                 {
10443                                         if (skyscissor[0] > scissor[0])
10444                                         {
10445                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10446                                                 skyscissor[0] = scissor[0];
10447                                         }
10448                                         if (skyscissor[1] > scissor[1])
10449                                         {
10450                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10451                                                 skyscissor[1] = scissor[1];
10452                                         }
10453                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10454                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10455                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10456                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10457                                 }
10458                                 else
10459                                         Vector4Copy(scissor, skyscissor);
10460                         }
10461                 }
10462         }
10463
10464         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10465         // skymasking on them, and Quake3 never did sky masking (unlike
10466         // software Quake and software Quake2), so disable the sky masking
10467         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10468         // and skymasking also looks very bad when noclipping outside the
10469         // level, so don't use it then either.
10470         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)
10471         {
10472                 R_Mesh_ResetTextureState();
10473                 if (skyrendermasked)
10474                 {
10475                         R_SetupShader_DepthOrShadow(false, false, false);
10476                         // depth-only (masking)
10477                         GL_ColorMask(0, 0, 0, 0);
10478                         // just to make sure that braindead drivers don't draw
10479                         // anything despite that colormask...
10480                         GL_BlendFunc(GL_ZERO, GL_ONE);
10481                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10482                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10483                 }
10484                 else
10485                 {
10486                         R_SetupShader_Generic_NoTexture(false, false);
10487                         // fog sky
10488                         GL_BlendFunc(GL_ONE, GL_ZERO);
10489                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10490                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10491                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10492                 }
10493                 RSurf_DrawBatch();
10494                 if (skyrendermasked)
10495                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10496         }
10497         R_Mesh_ResetTextureState();
10498         GL_Color(1, 1, 1, 1);
10499 }
10500
10501 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10502 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10503 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10504 {
10505         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10506                 return;
10507         if (prepass)
10508         {
10509                 // render screenspace normalmap to texture
10510                 GL_DepthMask(true);
10511                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10512                 RSurf_DrawBatch();
10513                 return;
10514         }
10515
10516         // bind lightmap texture
10517
10518         // water/refraction/reflection/camera surfaces have to be handled specially
10519         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10520         {
10521                 int start, end, startplaneindex;
10522                 for (start = 0;start < texturenumsurfaces;start = end)
10523                 {
10524                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10525                         if(startplaneindex < 0)
10526                         {
10527                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10528                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10529                                 end = start + 1;
10530                                 continue;
10531                         }
10532                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10533                                 ;
10534                         // now that we have a batch using the same planeindex, render it
10535                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10536                         {
10537                                 // render water or distortion background
10538                                 GL_DepthMask(true);
10539                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10540                                 RSurf_DrawBatch();
10541                                 // blend surface on top
10542                                 GL_DepthMask(false);
10543                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10544                                 RSurf_DrawBatch();
10545                         }
10546                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10547                         {
10548                                 // render surface with reflection texture as input
10549                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10550                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10551                                 RSurf_DrawBatch();
10552                         }
10553                 }
10554                 return;
10555         }
10556
10557         // render surface batch normally
10558         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10559         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10560         RSurf_DrawBatch();
10561 }
10562
10563 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10564 {
10565         // OpenGL 1.3 path - anything not completely ancient
10566         qboolean applycolor;
10567         qboolean applyfog;
10568         int layerindex;
10569         const texturelayer_t *layer;
10570         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);
10571         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10572
10573         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10574         {
10575                 vec4_t layercolor;
10576                 int layertexrgbscale;
10577                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10578                 {
10579                         if (layerindex == 0)
10580                                 GL_AlphaTest(true);
10581                         else
10582                         {
10583                                 GL_AlphaTest(false);
10584                                 GL_DepthFunc(GL_EQUAL);
10585                         }
10586                 }
10587                 GL_DepthMask(layer->depthmask && writedepth);
10588                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10589                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10590                 {
10591                         layertexrgbscale = 4;
10592                         VectorScale(layer->color, 0.25f, layercolor);
10593                 }
10594                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10595                 {
10596                         layertexrgbscale = 2;
10597                         VectorScale(layer->color, 0.5f, layercolor);
10598                 }
10599                 else
10600                 {
10601                         layertexrgbscale = 1;
10602                         VectorScale(layer->color, 1.0f, layercolor);
10603                 }
10604                 layercolor[3] = layer->color[3];
10605                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10606                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10607                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10608                 switch (layer->type)
10609                 {
10610                 case TEXTURELAYERTYPE_LITTEXTURE:
10611                         // single-pass lightmapped texture with 2x rgbscale
10612                         R_Mesh_TexBind(0, r_texture_white);
10613                         R_Mesh_TexMatrix(0, NULL);
10614                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10615                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10616                         R_Mesh_TexBind(1, layer->texture);
10617                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10618                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10619                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10620                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10621                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10622                         else if (FAKELIGHT_ENABLED)
10623                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10624                         else if (rsurface.uselightmaptexture)
10625                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10626                         else
10627                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10628                         break;
10629                 case TEXTURELAYERTYPE_TEXTURE:
10630                         // singletexture unlit texture with transparency support
10631                         R_Mesh_TexBind(0, layer->texture);
10632                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10633                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10634                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10635                         R_Mesh_TexBind(1, 0);
10636                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10637                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10638                         break;
10639                 case TEXTURELAYERTYPE_FOG:
10640                         // singletexture fogging
10641                         if (layer->texture)
10642                         {
10643                                 R_Mesh_TexBind(0, layer->texture);
10644                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10645                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10646                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10647                         }
10648                         else
10649                         {
10650                                 R_Mesh_TexBind(0, 0);
10651                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10652                         }
10653                         R_Mesh_TexBind(1, 0);
10654                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10655                         // generate a color array for the fog pass
10656                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10657                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10658                         RSurf_DrawBatch();
10659                         break;
10660                 default:
10661                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10662                 }
10663         }
10664         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10665         {
10666                 GL_DepthFunc(GL_LEQUAL);
10667                 GL_AlphaTest(false);
10668         }
10669 }
10670
10671 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10672 {
10673         // OpenGL 1.1 - crusty old voodoo path
10674         qboolean applyfog;
10675         int layerindex;
10676         const texturelayer_t *layer;
10677         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);
10678         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10679
10680         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10681         {
10682                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10683                 {
10684                         if (layerindex == 0)
10685                                 GL_AlphaTest(true);
10686                         else
10687                         {
10688                                 GL_AlphaTest(false);
10689                                 GL_DepthFunc(GL_EQUAL);
10690                         }
10691                 }
10692                 GL_DepthMask(layer->depthmask && writedepth);
10693                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10694                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10695                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10696                 switch (layer->type)
10697                 {
10698                 case TEXTURELAYERTYPE_LITTEXTURE:
10699                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10700                         {
10701                                 // two-pass lit texture with 2x rgbscale
10702                                 // first the lightmap pass
10703                                 R_Mesh_TexBind(0, r_texture_white);
10704                                 R_Mesh_TexMatrix(0, NULL);
10705                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10706                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10707                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10708                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10709                                 else if (FAKELIGHT_ENABLED)
10710                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10711                                 else if (rsurface.uselightmaptexture)
10712                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10713                                 else
10714                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10715                                 // then apply the texture to it
10716                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10717                                 R_Mesh_TexBind(0, layer->texture);
10718                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10719                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10720                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10721                                 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);
10722                         }
10723                         else
10724                         {
10725                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10726                                 R_Mesh_TexBind(0, layer->texture);
10727                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10728                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10729                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10730                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10731                                         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);
10732                                 else if (FAKELIGHT_ENABLED)
10733                                         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);
10734                                 else
10735                                         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);
10736                         }
10737                         break;
10738                 case TEXTURELAYERTYPE_TEXTURE:
10739                         // singletexture unlit texture with transparency support
10740                         R_Mesh_TexBind(0, layer->texture);
10741                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10742                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10743                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10744                         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);
10745                         break;
10746                 case TEXTURELAYERTYPE_FOG:
10747                         // singletexture fogging
10748                         if (layer->texture)
10749                         {
10750                                 R_Mesh_TexBind(0, layer->texture);
10751                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10752                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10753                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10754                         }
10755                         else
10756                         {
10757                                 R_Mesh_TexBind(0, 0);
10758                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10759                         }
10760                         // generate a color array for the fog pass
10761                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10762                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10763                         RSurf_DrawBatch();
10764                         break;
10765                 default:
10766                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10767                 }
10768         }
10769         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10770         {
10771                 GL_DepthFunc(GL_LEQUAL);
10772                 GL_AlphaTest(false);
10773         }
10774 }
10775
10776 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10777 {
10778         int vi;
10779         int j;
10780         r_vertexgeneric_t *batchvertex;
10781         float c[4];
10782         texture_t *t = rsurface.texture;
10783
10784 //      R_Mesh_ResetTextureState();
10785         R_SetupShader_Generic_NoTexture(false, false);
10786
10787         if(t && t->currentskinframe)
10788         {
10789                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10790                 c[3] *= t->currentalpha;
10791         }
10792         else
10793         {
10794                 c[0] = 1;
10795                 c[1] = 0;
10796                 c[2] = 1;
10797                 c[3] = 1;
10798         }
10799
10800         if (t->pantstexture || t->shirttexture)
10801         {
10802                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10803                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10804                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10805         }
10806
10807         // brighten it up (as texture value 127 means "unlit")
10808         c[0] *= 2 * r_refdef.view.colorscale;
10809         c[1] *= 2 * r_refdef.view.colorscale;
10810         c[2] *= 2 * r_refdef.view.colorscale;
10811
10812         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10813                 c[3] *= r_wateralpha.value;
10814
10815         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10816         {
10817                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10818                 GL_DepthMask(false);
10819         }
10820         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10821         {
10822                 GL_BlendFunc(GL_ONE, GL_ONE);
10823                 GL_DepthMask(false);
10824         }
10825         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10826         {
10827                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10828                 GL_DepthMask(false);
10829         }
10830         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10831         {
10832                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10833                 GL_DepthMask(false);
10834         }
10835         else
10836         {
10837                 GL_BlendFunc(GL_ONE, GL_ZERO);
10838                 GL_DepthMask(writedepth);
10839         }
10840
10841         if (r_showsurfaces.integer == 3)
10842         {
10843                 rsurface.passcolor4f = NULL;
10844
10845                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10846                 {
10847                         qboolean applycolor = true;
10848                         float one = 1.0;
10849
10850                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10851
10852                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10853                 }
10854                 else if (FAKELIGHT_ENABLED)
10855                 {
10856                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10857
10858                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10859                 }
10860                 else
10861                 {
10862                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10863
10864                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10865                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10866                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10867                         RSurf_DrawBatch_GL11_ApplyAmbient();
10868                 }
10869
10870                 if(!rsurface.passcolor4f)
10871                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10872
10873                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10874                 if(r_refdef.fogenabled)
10875                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10876                 RSurf_DrawBatch_GL11_ClampColor();
10877
10878                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10879                 R_SetupShader_Generic_NoTexture(false, false);
10880                 RSurf_DrawBatch();
10881         }
10882         else if (!r_refdef.view.showdebug)
10883         {
10884                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10885                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10886                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10887                 {
10888                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10889                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10890                 }
10891                 R_Mesh_PrepareVertices_Generic_Unlock();
10892                 RSurf_DrawBatch();
10893         }
10894         else if (r_showsurfaces.integer == 4)
10895         {
10896                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10897                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10898                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10899                 {
10900                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
10901                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10902                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10903                 }
10904                 R_Mesh_PrepareVertices_Generic_Unlock();
10905                 RSurf_DrawBatch();
10906         }
10907         else if (r_showsurfaces.integer == 2)
10908         {
10909                 const int *e;
10910                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10911                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10912                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10913                 {
10914                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10915                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10916                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10917                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10918                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10919                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10920                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10921                 }
10922                 R_Mesh_PrepareVertices_Generic_Unlock();
10923                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10924         }
10925         else
10926         {
10927                 int texturesurfaceindex;
10928                 int k;
10929                 const msurface_t *surface;
10930                 float surfacecolor4f[4];
10931                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10932                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10933                 vi = 0;
10934                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10935                 {
10936                         surface = texturesurfacelist[texturesurfaceindex];
10937                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10938                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10939                         for (j = 0;j < surface->num_vertices;j++)
10940                         {
10941                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10942                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10943                                 vi++;
10944                         }
10945                 }
10946                 R_Mesh_PrepareVertices_Generic_Unlock();
10947                 RSurf_DrawBatch();
10948         }
10949 }
10950
10951 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10952 {
10953         CHECKGLERROR
10954         RSurf_SetupDepthAndCulling();
10955         if (r_showsurfaces.integer)
10956         {
10957                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10958                 return;
10959         }
10960         switch (vid.renderpath)
10961         {
10962         case RENDERPATH_GL20:
10963         case RENDERPATH_D3D9:
10964         case RENDERPATH_D3D10:
10965         case RENDERPATH_D3D11:
10966         case RENDERPATH_SOFT:
10967         case RENDERPATH_GLES2:
10968                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10969                 break;
10970         case RENDERPATH_GL13:
10971         case RENDERPATH_GLES1:
10972                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10973                 break;
10974         case RENDERPATH_GL11:
10975                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10976                 break;
10977         }
10978         CHECKGLERROR
10979 }
10980
10981 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10982 {
10983         int i, j;
10984         int texturenumsurfaces, endsurface;
10985         texture_t *texture;
10986         const msurface_t *surface;
10987         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10988
10989         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10990                 RSurf_ActiveModelEntity(ent, false, false, false);
10991         else
10992         {
10993                 switch (vid.renderpath)
10994                 {
10995                 case RENDERPATH_GL20:
10996                 case RENDERPATH_D3D9:
10997                 case RENDERPATH_D3D10:
10998                 case RENDERPATH_D3D11:
10999                 case RENDERPATH_SOFT:
11000                 case RENDERPATH_GLES2:
11001                         RSurf_ActiveModelEntity(ent, true, true, false);
11002                         break;
11003                 case RENDERPATH_GL11:
11004                 case RENDERPATH_GL13:
11005                 case RENDERPATH_GLES1:
11006                         RSurf_ActiveModelEntity(ent, true, false, false);
11007                         break;
11008                 }
11009         }
11010
11011         if (r_transparentdepthmasking.integer)
11012         {
11013                 qboolean setup = false;
11014                 for (i = 0;i < numsurfaces;i = j)
11015                 {
11016                         j = i + 1;
11017                         surface = rsurface.modelsurfaces + surfacelist[i];
11018                         texture = surface->texture;
11019                         rsurface.texture = R_GetCurrentTexture(texture);
11020                         rsurface.lightmaptexture = NULL;
11021                         rsurface.deluxemaptexture = NULL;
11022                         rsurface.uselightmaptexture = false;
11023                         // scan ahead until we find a different texture
11024                         endsurface = min(i + 1024, numsurfaces);
11025                         texturenumsurfaces = 0;
11026                         texturesurfacelist[texturenumsurfaces++] = surface;
11027                         for (;j < endsurface;j++)
11028                         {
11029                                 surface = rsurface.modelsurfaces + surfacelist[j];
11030                                 if (texture != surface->texture)
11031                                         break;
11032                                 texturesurfacelist[texturenumsurfaces++] = surface;
11033                         }
11034                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11035                                 continue;
11036                         // render the range of surfaces as depth
11037                         if (!setup)
11038                         {
11039                                 setup = true;
11040                                 GL_ColorMask(0,0,0,0);
11041                                 GL_Color(1,1,1,1);
11042                                 GL_DepthTest(true);
11043                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11044                                 GL_DepthMask(true);
11045 //                              R_Mesh_ResetTextureState();
11046                         }
11047                         RSurf_SetupDepthAndCulling();
11048                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11049                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11050                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11051                         RSurf_DrawBatch();
11052                 }
11053                 if (setup)
11054                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11055         }
11056
11057         for (i = 0;i < numsurfaces;i = j)
11058         {
11059                 j = i + 1;
11060                 surface = rsurface.modelsurfaces + surfacelist[i];
11061                 texture = surface->texture;
11062                 rsurface.texture = R_GetCurrentTexture(texture);
11063                 // scan ahead until we find a different texture
11064                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11065                 texturenumsurfaces = 0;
11066                 texturesurfacelist[texturenumsurfaces++] = surface;
11067                 if(FAKELIGHT_ENABLED)
11068                 {
11069                         rsurface.lightmaptexture = NULL;
11070                         rsurface.deluxemaptexture = NULL;
11071                         rsurface.uselightmaptexture = false;
11072                         for (;j < endsurface;j++)
11073                         {
11074                                 surface = rsurface.modelsurfaces + surfacelist[j];
11075                                 if (texture != surface->texture)
11076                                         break;
11077                                 texturesurfacelist[texturenumsurfaces++] = surface;
11078                         }
11079                 }
11080                 else
11081                 {
11082                         rsurface.lightmaptexture = surface->lightmaptexture;
11083                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11084                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11085                         for (;j < endsurface;j++)
11086                         {
11087                                 surface = rsurface.modelsurfaces + surfacelist[j];
11088                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11089                                         break;
11090                                 texturesurfacelist[texturenumsurfaces++] = surface;
11091                         }
11092                 }
11093                 // render the range of surfaces
11094                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11095         }
11096         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11097 }
11098
11099 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11100 {
11101         // transparent surfaces get pushed off into the transparent queue
11102         int surfacelistindex;
11103         const msurface_t *surface;
11104         vec3_t tempcenter, center;
11105         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11106         {
11107                 surface = texturesurfacelist[surfacelistindex];
11108                 if (r_transparent_sortsurfacesbynearest.integer)
11109                 {
11110                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11111                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11112                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11113                 }
11114                 else
11115                 {
11116                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11117                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11118                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11119                 }
11120                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11121                 if (rsurface.entity->transparent_offset) // transparent offset
11122                 {
11123                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11124                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11125                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11126                 }
11127                 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);
11128         }
11129 }
11130
11131 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11132 {
11133         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11134                 return;
11135         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11136                 return;
11137         RSurf_SetupDepthAndCulling();
11138         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11139         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11140         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11141         RSurf_DrawBatch();
11142 }
11143
11144 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11145 {
11146         CHECKGLERROR
11147         if (depthonly)
11148                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11149         else if (prepass)
11150         {
11151                 if (!rsurface.texture->currentnumlayers)
11152                         return;
11153                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11154                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11155                 else
11156                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11157         }
11158         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11159                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11160         else if (!rsurface.texture->currentnumlayers)
11161                 return;
11162         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11163         {
11164                 // in the deferred case, transparent surfaces were queued during prepass
11165                 if (!r_shadow_usingdeferredprepass)
11166                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11167         }
11168         else
11169         {
11170                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11171                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11172         }
11173         CHECKGLERROR
11174 }
11175
11176 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11177 {
11178         int i, j;
11179         texture_t *texture;
11180         R_FrameData_SetMark();
11181         // break the surface list down into batches by texture and use of lightmapping
11182         for (i = 0;i < numsurfaces;i = j)
11183         {
11184                 j = i + 1;
11185                 // texture is the base texture pointer, rsurface.texture is the
11186                 // current frame/skin the texture is directing us to use (for example
11187                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11188                 // use skin 1 instead)
11189                 texture = surfacelist[i]->texture;
11190                 rsurface.texture = R_GetCurrentTexture(texture);
11191                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11192                 {
11193                         // if this texture is not the kind we want, skip ahead to the next one
11194                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11195                                 ;
11196                         continue;
11197                 }
11198                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11199                 {
11200                         rsurface.lightmaptexture = NULL;
11201                         rsurface.deluxemaptexture = NULL;
11202                         rsurface.uselightmaptexture = false;
11203                         // simply scan ahead until we find a different texture or lightmap state
11204                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11205                                 ;
11206                 }
11207                 else
11208                 {
11209                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11210                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11211                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11212                         // simply scan ahead until we find a different texture or lightmap state
11213                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11214                                 ;
11215                 }
11216                 // render the range of surfaces
11217                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11218         }
11219         R_FrameData_ReturnToMark();
11220 }
11221
11222 float locboxvertex3f[6*4*3] =
11223 {
11224         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11225         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11226         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11227         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11228         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11229         1,0,0, 0,0,0, 0,1,0, 1,1,0
11230 };
11231
11232 unsigned short locboxelements[6*2*3] =
11233 {
11234          0, 1, 2, 0, 2, 3,
11235          4, 5, 6, 4, 6, 7,
11236          8, 9,10, 8,10,11,
11237         12,13,14, 12,14,15,
11238         16,17,18, 16,18,19,
11239         20,21,22, 20,22,23
11240 };
11241
11242 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11243 {
11244         int i, j;
11245         cl_locnode_t *loc = (cl_locnode_t *)ent;
11246         vec3_t mins, size;
11247         float vertex3f[6*4*3];
11248         CHECKGLERROR
11249         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11250         GL_DepthMask(false);
11251         GL_DepthRange(0, 1);
11252         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11253         GL_DepthTest(true);
11254         GL_CullFace(GL_NONE);
11255         R_EntityMatrix(&identitymatrix);
11256
11257 //      R_Mesh_ResetTextureState();
11258
11259         i = surfacelist[0];
11260         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11261                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11262                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11263                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11264
11265         if (VectorCompare(loc->mins, loc->maxs))
11266         {
11267                 VectorSet(size, 2, 2, 2);
11268                 VectorMA(loc->mins, -0.5f, size, mins);
11269         }
11270         else
11271         {
11272                 VectorCopy(loc->mins, mins);
11273                 VectorSubtract(loc->maxs, loc->mins, size);
11274         }
11275
11276         for (i = 0;i < 6*4*3;)
11277                 for (j = 0;j < 3;j++, i++)
11278                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11279
11280         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11281         R_SetupShader_Generic_NoTexture(false, false);
11282         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11283 }
11284
11285 void R_DrawLocs(void)
11286 {
11287         int index;
11288         cl_locnode_t *loc, *nearestloc;
11289         vec3_t center;
11290         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11291         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11292         {
11293                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11294                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11295         }
11296 }
11297
11298 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11299 {
11300         if (decalsystem->decals)
11301                 Mem_Free(decalsystem->decals);
11302         memset(decalsystem, 0, sizeof(*decalsystem));
11303 }
11304
11305 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)
11306 {
11307         tridecal_t *decal;
11308         tridecal_t *decals;
11309         int i;
11310
11311         // expand or initialize the system
11312         if (decalsystem->maxdecals <= decalsystem->numdecals)
11313         {
11314                 decalsystem_t old = *decalsystem;
11315                 qboolean useshortelements;
11316                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11317                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11318                 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)));
11319                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11320                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11321                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11322                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11323                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11324                 if (decalsystem->numdecals)
11325                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11326                 if (old.decals)
11327                         Mem_Free(old.decals);
11328                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11329                         decalsystem->element3i[i] = i;
11330                 if (useshortelements)
11331                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11332                                 decalsystem->element3s[i] = i;
11333         }
11334
11335         // grab a decal and search for another free slot for the next one
11336         decals = decalsystem->decals;
11337         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11338         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11339                 ;
11340         decalsystem->freedecal = i;
11341         if (decalsystem->numdecals <= i)
11342                 decalsystem->numdecals = i + 1;
11343
11344         // initialize the decal
11345         decal->lived = 0;
11346         decal->triangleindex = triangleindex;
11347         decal->surfaceindex = surfaceindex;
11348         decal->decalsequence = decalsequence;
11349         decal->color4f[0][0] = c0[0];
11350         decal->color4f[0][1] = c0[1];
11351         decal->color4f[0][2] = c0[2];
11352         decal->color4f[0][3] = 1;
11353         decal->color4f[1][0] = c1[0];
11354         decal->color4f[1][1] = c1[1];
11355         decal->color4f[1][2] = c1[2];
11356         decal->color4f[1][3] = 1;
11357         decal->color4f[2][0] = c2[0];
11358         decal->color4f[2][1] = c2[1];
11359         decal->color4f[2][2] = c2[2];
11360         decal->color4f[2][3] = 1;
11361         decal->vertex3f[0][0] = v0[0];
11362         decal->vertex3f[0][1] = v0[1];
11363         decal->vertex3f[0][2] = v0[2];
11364         decal->vertex3f[1][0] = v1[0];
11365         decal->vertex3f[1][1] = v1[1];
11366         decal->vertex3f[1][2] = v1[2];
11367         decal->vertex3f[2][0] = v2[0];
11368         decal->vertex3f[2][1] = v2[1];
11369         decal->vertex3f[2][2] = v2[2];
11370         decal->texcoord2f[0][0] = t0[0];
11371         decal->texcoord2f[0][1] = t0[1];
11372         decal->texcoord2f[1][0] = t1[0];
11373         decal->texcoord2f[1][1] = t1[1];
11374         decal->texcoord2f[2][0] = t2[0];
11375         decal->texcoord2f[2][1] = t2[1];
11376         TriangleNormal(v0, v1, v2, decal->plane);
11377         VectorNormalize(decal->plane);
11378         decal->plane[3] = DotProduct(v0, decal->plane);
11379 }
11380
11381 extern cvar_t cl_decals_bias;
11382 extern cvar_t cl_decals_models;
11383 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11384 // baseparms, parms, temps
11385 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)
11386 {
11387         int cornerindex;
11388         int index;
11389         float v[9][3];
11390         const float *vertex3f;
11391         const float *normal3f;
11392         int numpoints;
11393         float points[2][9][3];
11394         float temp[3];
11395         float tc[9][2];
11396         float f;
11397         float c[9][4];
11398         const int *e;
11399
11400         e = rsurface.modelelement3i + 3*triangleindex;
11401
11402         vertex3f = rsurface.modelvertex3f;
11403         normal3f = rsurface.modelnormal3f;
11404
11405         if (normal3f)
11406         {
11407                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11408                 {
11409                         index = 3*e[cornerindex];
11410                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11411                 }
11412         }
11413         else
11414         {
11415                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11416                 {
11417                         index = 3*e[cornerindex];
11418                         VectorCopy(vertex3f + index, v[cornerindex]);
11419                 }
11420         }
11421
11422         // cull backfaces
11423         //TriangleNormal(v[0], v[1], v[2], normal);
11424         //if (DotProduct(normal, localnormal) < 0.0f)
11425         //      continue;
11426         // clip by each of the box planes formed from the projection matrix
11427         // if anything survives, we emit the decal
11428         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]);
11429         if (numpoints < 3)
11430                 return;
11431         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]);
11432         if (numpoints < 3)
11433                 return;
11434         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]);
11435         if (numpoints < 3)
11436                 return;
11437         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]);
11438         if (numpoints < 3)
11439                 return;
11440         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]);
11441         if (numpoints < 3)
11442                 return;
11443         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]);
11444         if (numpoints < 3)
11445                 return;
11446         // some part of the triangle survived, so we have to accept it...
11447         if (dynamic)
11448         {
11449                 // dynamic always uses the original triangle
11450                 numpoints = 3;
11451                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11452                 {
11453                         index = 3*e[cornerindex];
11454                         VectorCopy(vertex3f + index, v[cornerindex]);
11455                 }
11456         }
11457         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11458         {
11459                 // convert vertex positions to texcoords
11460                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11461                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11462                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11463                 // calculate distance fade from the projection origin
11464                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11465                 f = bound(0.0f, f, 1.0f);
11466                 c[cornerindex][0] = r * f;
11467                 c[cornerindex][1] = g * f;
11468                 c[cornerindex][2] = b * f;
11469                 c[cornerindex][3] = 1.0f;
11470                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11471         }
11472         if (dynamic)
11473                 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);
11474         else
11475                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11476                         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);
11477 }
11478 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)
11479 {
11480         matrix4x4_t projection;
11481         decalsystem_t *decalsystem;
11482         qboolean dynamic;
11483         dp_model_t *model;
11484         const msurface_t *surface;
11485         const msurface_t *surfaces;
11486         const int *surfacelist;
11487         const texture_t *texture;
11488         int numtriangles;
11489         int numsurfacelist;
11490         int surfacelistindex;
11491         int surfaceindex;
11492         int triangleindex;
11493         float localorigin[3];
11494         float localnormal[3];
11495         float localmins[3];
11496         float localmaxs[3];
11497         float localsize;
11498         //float normal[3];
11499         float planes[6][4];
11500         float angles[3];
11501         bih_t *bih;
11502         int bih_triangles_count;
11503         int bih_triangles[256];
11504         int bih_surfaces[256];
11505
11506         decalsystem = &ent->decalsystem;
11507         model = ent->model;
11508         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11509         {
11510                 R_DecalSystem_Reset(&ent->decalsystem);
11511                 return;
11512         }
11513
11514         if (!model->brush.data_leafs && !cl_decals_models.integer)
11515         {
11516                 if (decalsystem->model)
11517                         R_DecalSystem_Reset(decalsystem);
11518                 return;
11519         }
11520
11521         if (decalsystem->model != model)
11522                 R_DecalSystem_Reset(decalsystem);
11523         decalsystem->model = model;
11524
11525         RSurf_ActiveModelEntity(ent, true, false, false);
11526
11527         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11528         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11529         VectorNormalize(localnormal);
11530         localsize = worldsize*rsurface.inversematrixscale;
11531         localmins[0] = localorigin[0] - localsize;
11532         localmins[1] = localorigin[1] - localsize;
11533         localmins[2] = localorigin[2] - localsize;
11534         localmaxs[0] = localorigin[0] + localsize;
11535         localmaxs[1] = localorigin[1] + localsize;
11536         localmaxs[2] = localorigin[2] + localsize;
11537
11538         //VectorCopy(localnormal, planes[4]);
11539         //VectorVectors(planes[4], planes[2], planes[0]);
11540         AnglesFromVectors(angles, localnormal, NULL, false);
11541         AngleVectors(angles, planes[0], planes[2], planes[4]);
11542         VectorNegate(planes[0], planes[1]);
11543         VectorNegate(planes[2], planes[3]);
11544         VectorNegate(planes[4], planes[5]);
11545         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11546         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11547         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11548         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11549         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11550         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11551
11552 #if 1
11553 // works
11554 {
11555         matrix4x4_t forwardprojection;
11556         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11557         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11558 }
11559 #else
11560 // broken
11561 {
11562         float projectionvector[4][3];
11563         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11564         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11565         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11566         projectionvector[0][0] = planes[0][0] * ilocalsize;
11567         projectionvector[0][1] = planes[1][0] * ilocalsize;
11568         projectionvector[0][2] = planes[2][0] * ilocalsize;
11569         projectionvector[1][0] = planes[0][1] * ilocalsize;
11570         projectionvector[1][1] = planes[1][1] * ilocalsize;
11571         projectionvector[1][2] = planes[2][1] * ilocalsize;
11572         projectionvector[2][0] = planes[0][2] * ilocalsize;
11573         projectionvector[2][1] = planes[1][2] * ilocalsize;
11574         projectionvector[2][2] = planes[2][2] * ilocalsize;
11575         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11576         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11577         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11578         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11579 }
11580 #endif
11581
11582         dynamic = model->surfmesh.isanimated;
11583         numsurfacelist = model->nummodelsurfaces;
11584         surfacelist = model->sortedmodelsurfaces;
11585         surfaces = model->data_surfaces;
11586
11587         bih = NULL;
11588         bih_triangles_count = -1;
11589         if(!dynamic)
11590         {
11591                 if(model->render_bih.numleafs)
11592                         bih = &model->render_bih;
11593                 else if(model->collision_bih.numleafs)
11594                         bih = &model->collision_bih;
11595         }
11596         if(bih)
11597                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11598         if(bih_triangles_count == 0)
11599                 return;
11600         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11601                 return;
11602         if(bih_triangles_count > 0)
11603         {
11604                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11605                 {
11606                         surfaceindex = bih_surfaces[triangleindex];
11607                         surface = surfaces + surfaceindex;
11608                         texture = surface->texture;
11609                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11610                                 continue;
11611                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11612                                 continue;
11613                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11614                 }
11615         }
11616         else
11617         {
11618                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11619                 {
11620                         surfaceindex = surfacelist[surfacelistindex];
11621                         surface = surfaces + surfaceindex;
11622                         // check cull box first because it rejects more than any other check
11623                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11624                                 continue;
11625                         // skip transparent surfaces
11626                         texture = surface->texture;
11627                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11628                                 continue;
11629                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11630                                 continue;
11631                         numtriangles = surface->num_triangles;
11632                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11633                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11634                 }
11635         }
11636 }
11637
11638 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11639 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)
11640 {
11641         int renderentityindex;
11642         float worldmins[3];
11643         float worldmaxs[3];
11644         entity_render_t *ent;
11645
11646         if (!cl_decals_newsystem.integer)
11647                 return;
11648
11649         worldmins[0] = worldorigin[0] - worldsize;
11650         worldmins[1] = worldorigin[1] - worldsize;
11651         worldmins[2] = worldorigin[2] - worldsize;
11652         worldmaxs[0] = worldorigin[0] + worldsize;
11653         worldmaxs[1] = worldorigin[1] + worldsize;
11654         worldmaxs[2] = worldorigin[2] + worldsize;
11655
11656         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11657
11658         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11659         {
11660                 ent = r_refdef.scene.entities[renderentityindex];
11661                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11662                         continue;
11663
11664                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11665         }
11666 }
11667
11668 typedef struct r_decalsystem_splatqueue_s
11669 {
11670         vec3_t worldorigin;
11671         vec3_t worldnormal;
11672         float color[4];
11673         float tcrange[4];
11674         float worldsize;
11675         unsigned int decalsequence;
11676 }
11677 r_decalsystem_splatqueue_t;
11678
11679 int r_decalsystem_numqueued = 0;
11680 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11681
11682 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)
11683 {
11684         r_decalsystem_splatqueue_t *queue;
11685
11686         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11687                 return;
11688
11689         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11690         VectorCopy(worldorigin, queue->worldorigin);
11691         VectorCopy(worldnormal, queue->worldnormal);
11692         Vector4Set(queue->color, r, g, b, a);
11693         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11694         queue->worldsize = worldsize;
11695         queue->decalsequence = cl.decalsequence++;
11696 }
11697
11698 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11699 {
11700         int i;
11701         r_decalsystem_splatqueue_t *queue;
11702
11703         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11704                 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);
11705         r_decalsystem_numqueued = 0;
11706 }
11707
11708 extern cvar_t cl_decals_max;
11709 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11710 {
11711         int i;
11712         decalsystem_t *decalsystem = &ent->decalsystem;
11713         int numdecals;
11714         unsigned int killsequence;
11715         tridecal_t *decal;
11716         float frametime;
11717         float lifetime;
11718
11719         if (!decalsystem->numdecals)
11720                 return;
11721
11722         if (r_showsurfaces.integer)
11723                 return;
11724
11725         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11726         {
11727                 R_DecalSystem_Reset(decalsystem);
11728                 return;
11729         }
11730
11731         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11732         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11733
11734         if (decalsystem->lastupdatetime)
11735                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11736         else
11737                 frametime = 0;
11738         decalsystem->lastupdatetime = r_refdef.scene.time;
11739         numdecals = decalsystem->numdecals;
11740
11741         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11742         {
11743                 if (decal->color4f[0][3])
11744                 {
11745                         decal->lived += frametime;
11746                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11747                         {
11748                                 memset(decal, 0, sizeof(*decal));
11749                                 if (decalsystem->freedecal > i)
11750                                         decalsystem->freedecal = i;
11751                         }
11752                 }
11753         }
11754         decal = decalsystem->decals;
11755         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11756                 numdecals--;
11757
11758         // collapse the array by shuffling the tail decals into the gaps
11759         for (;;)
11760         {
11761                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11762                         decalsystem->freedecal++;
11763                 if (decalsystem->freedecal == numdecals)
11764                         break;
11765                 decal[decalsystem->freedecal] = decal[--numdecals];
11766         }
11767
11768         decalsystem->numdecals = numdecals;
11769
11770         if (numdecals <= 0)
11771         {
11772                 // if there are no decals left, reset decalsystem
11773                 R_DecalSystem_Reset(decalsystem);
11774         }
11775 }
11776
11777 extern skinframe_t *decalskinframe;
11778 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11779 {
11780         int i;
11781         decalsystem_t *decalsystem = &ent->decalsystem;
11782         int numdecals;
11783         tridecal_t *decal;
11784         float faderate;
11785         float alpha;
11786         float *v3f;
11787         float *c4f;
11788         float *t2f;
11789         const int *e;
11790         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11791         int numtris = 0;
11792
11793         numdecals = decalsystem->numdecals;
11794         if (!numdecals)
11795                 return;
11796
11797         if (r_showsurfaces.integer)
11798                 return;
11799
11800         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11801         {
11802                 R_DecalSystem_Reset(decalsystem);
11803                 return;
11804         }
11805
11806         // if the model is static it doesn't matter what value we give for
11807         // wantnormals and wanttangents, so this logic uses only rules applicable
11808         // to a model, knowing that they are meaningless otherwise
11809         RSurf_ActiveModelEntity(ent, false, false, false);
11810
11811         decalsystem->lastupdatetime = r_refdef.scene.time;
11812
11813         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11814
11815         // update vertex positions for animated models
11816         v3f = decalsystem->vertex3f;
11817         c4f = decalsystem->color4f;
11818         t2f = decalsystem->texcoord2f;
11819         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11820         {
11821                 if (!decal->color4f[0][3])
11822                         continue;
11823
11824                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11825                         continue;
11826
11827                 // skip backfaces
11828                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11829                         continue;
11830
11831                 // update color values for fading decals
11832                 if (decal->lived >= cl_decals_time.value)
11833                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11834                 else
11835                         alpha = 1.0f;
11836
11837                 c4f[ 0] = decal->color4f[0][0] * alpha;
11838                 c4f[ 1] = decal->color4f[0][1] * alpha;
11839                 c4f[ 2] = decal->color4f[0][2] * alpha;
11840                 c4f[ 3] = 1;
11841                 c4f[ 4] = decal->color4f[1][0] * alpha;
11842                 c4f[ 5] = decal->color4f[1][1] * alpha;
11843                 c4f[ 6] = decal->color4f[1][2] * alpha;
11844                 c4f[ 7] = 1;
11845                 c4f[ 8] = decal->color4f[2][0] * alpha;
11846                 c4f[ 9] = decal->color4f[2][1] * alpha;
11847                 c4f[10] = decal->color4f[2][2] * alpha;
11848                 c4f[11] = 1;
11849
11850                 t2f[0] = decal->texcoord2f[0][0];
11851                 t2f[1] = decal->texcoord2f[0][1];
11852                 t2f[2] = decal->texcoord2f[1][0];
11853                 t2f[3] = decal->texcoord2f[1][1];
11854                 t2f[4] = decal->texcoord2f[2][0];
11855                 t2f[5] = decal->texcoord2f[2][1];
11856
11857                 // update vertex positions for animated models
11858                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11859                 {
11860                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11861                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11862                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11863                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11864                 }
11865                 else
11866                 {
11867                         VectorCopy(decal->vertex3f[0], v3f);
11868                         VectorCopy(decal->vertex3f[1], v3f + 3);
11869                         VectorCopy(decal->vertex3f[2], v3f + 6);
11870                 }
11871
11872                 if (r_refdef.fogenabled)
11873                 {
11874                         alpha = RSurf_FogVertex(v3f);
11875                         VectorScale(c4f, alpha, c4f);
11876                         alpha = RSurf_FogVertex(v3f + 3);
11877                         VectorScale(c4f + 4, alpha, c4f + 4);
11878                         alpha = RSurf_FogVertex(v3f + 6);
11879                         VectorScale(c4f + 8, alpha, c4f + 8);
11880                 }
11881
11882                 v3f += 9;
11883                 c4f += 12;
11884                 t2f += 6;
11885                 numtris++;
11886         }
11887
11888         if (numtris > 0)
11889         {
11890                 r_refdef.stats[r_stat_drawndecals] += numtris;
11891
11892                 // now render the decals all at once
11893                 // (this assumes they all use one particle font texture!)
11894                 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);
11895 //              R_Mesh_ResetTextureState();
11896                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11897                 GL_DepthMask(false);
11898                 GL_DepthRange(0, 1);
11899                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11900                 GL_DepthTest(true);
11901                 GL_CullFace(GL_NONE);
11902                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11903                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11904                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11905         }
11906 }
11907
11908 static void R_DrawModelDecals(void)
11909 {
11910         int i, numdecals;
11911
11912         // fade faster when there are too many decals
11913         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11914         for (i = 0;i < r_refdef.scene.numentities;i++)
11915                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11916
11917         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11918         for (i = 0;i < r_refdef.scene.numentities;i++)
11919                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11920                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11921
11922         R_DecalSystem_ApplySplatEntitiesQueue();
11923
11924         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11925         for (i = 0;i < r_refdef.scene.numentities;i++)
11926                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11927
11928         r_refdef.stats[r_stat_totaldecals] += numdecals;
11929
11930         if (r_showsurfaces.integer)
11931                 return;
11932
11933         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11934
11935         for (i = 0;i < r_refdef.scene.numentities;i++)
11936         {
11937                 if (!r_refdef.viewcache.entityvisible[i])
11938                         continue;
11939                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11940                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11941         }
11942 }
11943
11944 extern cvar_t mod_collision_bih;
11945 static void R_DrawDebugModel(void)
11946 {
11947         entity_render_t *ent = rsurface.entity;
11948         int i, j, flagsmask;
11949         const msurface_t *surface;
11950         dp_model_t *model = ent->model;
11951
11952         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11953                 return;
11954
11955         if (r_showoverdraw.value > 0)
11956         {
11957                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11958                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11959                 R_SetupShader_Generic_NoTexture(false, false);
11960                 GL_DepthTest(false);
11961                 GL_DepthMask(false);
11962                 GL_DepthRange(0, 1);
11963                 GL_BlendFunc(GL_ONE, GL_ONE);
11964                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11965                 {
11966                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11967                                 continue;
11968                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11969                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11970                         {
11971                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11972                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11973                                 if (!rsurface.texture->currentlayers->depthmask)
11974                                         GL_Color(c, 0, 0, 1.0f);
11975                                 else if (ent == r_refdef.scene.worldentity)
11976                                         GL_Color(c, c, c, 1.0f);
11977                                 else
11978                                         GL_Color(0, c, 0, 1.0f);
11979                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11980                                 RSurf_DrawBatch();
11981                         }
11982                 }
11983                 rsurface.texture = NULL;
11984         }
11985
11986         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11987
11988 //      R_Mesh_ResetTextureState();
11989         R_SetupShader_Generic_NoTexture(false, false);
11990         GL_DepthRange(0, 1);
11991         GL_DepthTest(!r_showdisabledepthtest.integer);
11992         GL_DepthMask(false);
11993         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11994
11995         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11996         {
11997                 int triangleindex;
11998                 int bihleafindex;
11999                 qboolean cullbox = false;
12000                 const q3mbrush_t *brush;
12001                 const bih_t *bih = &model->collision_bih;
12002                 const bih_leaf_t *bihleaf;
12003                 float vertex3f[3][3];
12004                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12005                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12006                 {
12007                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12008                                 continue;
12009                         switch (bihleaf->type)
12010                         {
12011                         case BIH_BRUSH:
12012                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12013                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12014                                 {
12015                                         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);
12016                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12017                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12018                                 }
12019                                 break;
12020                         case BIH_COLLISIONTRIANGLE:
12021                                 triangleindex = bihleaf->itemindex;
12022                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12023                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12024                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12025                                 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);
12026                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12027                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12028                                 break;
12029                         case BIH_RENDERTRIANGLE:
12030                                 triangleindex = bihleaf->itemindex;
12031                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12032                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12033                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12034                                 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);
12035                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12036                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12037                                 break;
12038                         }
12039                 }
12040         }
12041
12042         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12043
12044 #ifndef USE_GLES2
12045         if (r_showtris.integer && qglPolygonMode)
12046         {
12047                 if (r_showdisabledepthtest.integer)
12048                 {
12049                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12050                         GL_DepthMask(false);
12051                 }
12052                 else
12053                 {
12054                         GL_BlendFunc(GL_ONE, GL_ZERO);
12055                         GL_DepthMask(true);
12056                 }
12057                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12058                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12059                 {
12060                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12061                                 continue;
12062                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12063                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12064                         {
12065                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12066                                 if (!rsurface.texture->currentlayers->depthmask)
12067                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12068                                 else if (ent == r_refdef.scene.worldentity)
12069                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12070                                 else
12071                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12072                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12073                                 RSurf_DrawBatch();
12074                         }
12075                 }
12076                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12077                 rsurface.texture = NULL;
12078         }
12079
12080         if (r_shownormals.value != 0 && qglBegin)
12081         {
12082                 int l, k;
12083                 vec3_t v;
12084                 if (r_showdisabledepthtest.integer)
12085                 {
12086                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12087                         GL_DepthMask(false);
12088                 }
12089                 else
12090                 {
12091                         GL_BlendFunc(GL_ONE, GL_ZERO);
12092                         GL_DepthMask(true);
12093                 }
12094                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12095                 {
12096                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12097                                 continue;
12098                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12099                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12100                         {
12101                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12102                                 qglBegin(GL_LINES);
12103                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12104                                 {
12105                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12106                                         {
12107                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12108                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12109                                                 qglVertex3f(v[0], v[1], v[2]);
12110                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12111                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12112                                                 qglVertex3f(v[0], v[1], v[2]);
12113                                         }
12114                                 }
12115                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12116                                 {
12117                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12118                                         {
12119                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12120                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12121                                                 qglVertex3f(v[0], v[1], v[2]);
12122                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12123                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12124                                                 qglVertex3f(v[0], v[1], v[2]);
12125                                         }
12126                                 }
12127                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12128                                 {
12129                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12130                                         {
12131                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12132                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12133                                                 qglVertex3f(v[0], v[1], v[2]);
12134                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12135                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12136                                                 qglVertex3f(v[0], v[1], v[2]);
12137                                         }
12138                                 }
12139                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12140                                 {
12141                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12142                                         {
12143                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12144                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12145                                                 qglVertex3f(v[0], v[1], v[2]);
12146                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12147                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12148                                                 qglVertex3f(v[0], v[1], v[2]);
12149                                         }
12150                                 }
12151                                 qglEnd();
12152                                 CHECKGLERROR
12153                         }
12154                 }
12155                 rsurface.texture = NULL;
12156         }
12157 #endif
12158 }
12159
12160 int r_maxsurfacelist = 0;
12161 const msurface_t **r_surfacelist = NULL;
12162 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12163 {
12164         int i, j, endj, flagsmask;
12165         dp_model_t *model = ent->model;
12166         msurface_t *surfaces;
12167         unsigned char *update;
12168         int numsurfacelist = 0;
12169         if (model == NULL)
12170                 return;
12171
12172         if (r_maxsurfacelist < model->num_surfaces)
12173         {
12174                 r_maxsurfacelist = model->num_surfaces;
12175                 if (r_surfacelist)
12176                         Mem_Free((msurface_t **)r_surfacelist);
12177                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12178         }
12179
12180         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12181                 RSurf_ActiveModelEntity(ent, false, false, false);
12182         else if (prepass)
12183                 RSurf_ActiveModelEntity(ent, true, true, true);
12184         else if (depthonly)
12185         {
12186                 switch (vid.renderpath)
12187                 {
12188                 case RENDERPATH_GL20:
12189                 case RENDERPATH_D3D9:
12190                 case RENDERPATH_D3D10:
12191                 case RENDERPATH_D3D11:
12192                 case RENDERPATH_SOFT:
12193                 case RENDERPATH_GLES2:
12194                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12195                         break;
12196                 case RENDERPATH_GL11:
12197                 case RENDERPATH_GL13:
12198                 case RENDERPATH_GLES1:
12199                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12200                         break;
12201                 }
12202         }
12203         else
12204         {
12205                 switch (vid.renderpath)
12206                 {
12207                 case RENDERPATH_GL20:
12208                 case RENDERPATH_D3D9:
12209                 case RENDERPATH_D3D10:
12210                 case RENDERPATH_D3D11:
12211                 case RENDERPATH_SOFT:
12212                 case RENDERPATH_GLES2:
12213                         RSurf_ActiveModelEntity(ent, true, true, false);
12214                         break;
12215                 case RENDERPATH_GL11:
12216                 case RENDERPATH_GL13:
12217                 case RENDERPATH_GLES1:
12218                         RSurf_ActiveModelEntity(ent, true, false, false);
12219                         break;
12220                 }
12221         }
12222
12223         surfaces = model->data_surfaces;
12224         update = model->brushq1.lightmapupdateflags;
12225
12226         // update light styles
12227         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12228         {
12229                 model_brush_lightstyleinfo_t *style;
12230                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12231                 {
12232                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12233                         {
12234                                 int *list = style->surfacelist;
12235                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12236                                 for (j = 0;j < style->numsurfaces;j++)
12237                                         update[list[j]] = true;
12238                         }
12239                 }
12240         }
12241
12242         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12243
12244         if (debug)
12245         {
12246                 R_DrawDebugModel();
12247                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12248                 return;
12249         }
12250
12251         rsurface.lightmaptexture = NULL;
12252         rsurface.deluxemaptexture = NULL;
12253         rsurface.uselightmaptexture = false;
12254         rsurface.texture = NULL;
12255         rsurface.rtlight = NULL;
12256         numsurfacelist = 0;
12257         // add visible surfaces to draw list
12258         if (ent == r_refdef.scene.worldentity)
12259         {
12260                 // for the world entity, check surfacevisible
12261                 for (i = 0;i < model->nummodelsurfaces;i++)
12262                 {
12263                         j = model->sortedmodelsurfaces[i];
12264                         if (r_refdef.viewcache.world_surfacevisible[j])
12265                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12266                 }
12267         }
12268         else
12269         {
12270                 // add all surfaces
12271                 for (i = 0; i < model->nummodelsurfaces; i++)
12272                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12273         }
12274         // don't do anything if there were no surfaces
12275         if (!numsurfacelist)
12276         {
12277                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12278                 return;
12279         }
12280         // update lightmaps if needed
12281         if (update)
12282         {
12283                 int updated = 0;
12284                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12285                 {
12286                         if (update[j])
12287                         {
12288                                 updated++;
12289                                 R_BuildLightMap(ent, surfaces + j);
12290                         }
12291                 }
12292         }
12293
12294         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12295
12296         // add to stats if desired
12297         if (r_speeds.integer && !skysurfaces && !depthonly)
12298         {
12299                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12300                 for (j = 0;j < numsurfacelist;j++)
12301                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12302         }
12303
12304         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12305 }
12306
12307 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12308 {
12309         int q;
12310         static texture_t texture;
12311         static msurface_t surface;
12312         const msurface_t *surfacelist = &surface;
12313
12314         // fake enough texture and surface state to render this geometry
12315
12316         texture.update_lastrenderframe = -1; // regenerate this texture
12317         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12318         texture.basealpha = 1.0f;
12319         texture.currentskinframe = skinframe;
12320         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12321         texture.offsetmapping = OFFSETMAPPING_OFF;
12322         texture.offsetscale = 1;
12323         texture.specularscalemod = 1;
12324         texture.specularpowermod = 1;
12325         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12326         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12327         // JUST GREP FOR "specularscalemod = 1".
12328
12329         for (q = 0; q < 3; q++)
12330         {
12331                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12332                 texture.render_modellight_lightdir[q] = q == 2;
12333                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12334                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12335                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12336                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12337                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12338                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12339                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12340                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12341         }
12342         texture.currentalpha = 1.0f;
12343
12344         surface.texture = &texture;
12345         surface.num_triangles = numtriangles;
12346         surface.num_firsttriangle = firsttriangle;
12347         surface.num_vertices = numvertices;
12348         surface.num_firstvertex = firstvertex;
12349
12350         // now render it
12351         rsurface.texture = R_GetCurrentTexture(surface.texture);
12352         rsurface.lightmaptexture = NULL;
12353         rsurface.deluxemaptexture = NULL;
12354         rsurface.uselightmaptexture = false;
12355         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12356 }
12357
12358 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)
12359 {
12360         static msurface_t surface;
12361         const msurface_t *surfacelist = &surface;
12362
12363         // fake enough texture and surface state to render this geometry
12364         surface.texture = texture;
12365         surface.num_triangles = numtriangles;
12366         surface.num_firsttriangle = firsttriangle;
12367         surface.num_vertices = numvertices;
12368         surface.num_firstvertex = firstvertex;
12369
12370         // now render it
12371         rsurface.texture = R_GetCurrentTexture(surface.texture);
12372         rsurface.lightmaptexture = NULL;
12373         rsurface.deluxemaptexture = NULL;
12374         rsurface.uselightmaptexture = false;
12375         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12376 }