]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added r_cullentities_trace_expand and pad cvars, these configure additional ways...
[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_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
118 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
119 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
120 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"};
121 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
122 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
123 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
124
125 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
126 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
127 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
128
129 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"};
130 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
132 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"};
133 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"};
134
135 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
136 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
137 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
138 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."};
139 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
140 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
141 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
142 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."};
143 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
144 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
145 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."};
146 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."};
147 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
148 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"};
149 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"};
150 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
152 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
153 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
154 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
155 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"};
156 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
157 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
158 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
159 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
160 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
161
162 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
163 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
164 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
165 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
166 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
167 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
168 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
169 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
170
171 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)"};
172 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"};
173
174 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
175 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
176 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
177
178 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"};
179 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"};
180 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)"};
181 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"};
182 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
183 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
184 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"};
185 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)"};
186 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)"};
187 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
188
189 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
190 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)"};
191 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
192 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)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
194 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)"};
195 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)"};
196 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
197 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"};
198 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."};
199 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206 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)"};
207 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)"};
208
209 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)"};
210 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)"};
211 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
212 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"};
213 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
214 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
215 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
216 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"};
217 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"};
218
219 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
220 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
221 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
222 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
223
224 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
225 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
226
227 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
228 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
229 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
230 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
231 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
232 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
233
234 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
235 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
236 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
237 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
238 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
240 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
241 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
242 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
243 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
244
245 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"};
246
247 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"};
248
249 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
250
251 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
252
253 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)"};
254 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)"};
255 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
256 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
257
258 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
259 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"};
260
261 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."};
262
263 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)"};
264 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
265 {
266         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
267         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
269         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
270 };
271
272 extern cvar_t v_glslgamma_2d;
273
274 extern qboolean v_flipped_state;
275
276 r_framebufferstate_t r_fb;
277
278 /// shadow volume bsp struct with automatically growing nodes buffer
279 svbsp_t r_svbsp;
280
281 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
282
283 rtexture_t *r_texture_blanknormalmap;
284 rtexture_t *r_texture_white;
285 rtexture_t *r_texture_grey128;
286 rtexture_t *r_texture_black;
287 rtexture_t *r_texture_notexture;
288 rtexture_t *r_texture_whitecube;
289 rtexture_t *r_texture_normalizationcube;
290 rtexture_t *r_texture_fogattenuation;
291 rtexture_t *r_texture_fogheighttexture;
292 rtexture_t *r_texture_gammaramps;
293 unsigned int r_texture_gammaramps_serial;
294 //rtexture_t *r_texture_fogintensity;
295 rtexture_t *r_texture_reflectcube;
296
297 // TODO: hash lookups?
298 typedef struct cubemapinfo_s
299 {
300         char basename[64];
301         rtexture_t *texture;
302 }
303 cubemapinfo_t;
304
305 int r_texture_numcubemaps;
306 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
307
308 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
309 unsigned int r_numqueries;
310 unsigned int r_maxqueries;
311
312 typedef struct r_qwskincache_s
313 {
314         char name[MAX_QPATH];
315         skinframe_t *skinframe;
316 }
317 r_qwskincache_t;
318
319 static r_qwskincache_t *r_qwskincache;
320 static int r_qwskincache_size;
321
322 /// vertex coordinates for a quad that covers the screen exactly
323 extern const float r_screenvertex3f[12];
324 const float r_screenvertex3f[12] =
325 {
326         0, 0, 0,
327         1, 0, 0,
328         1, 1, 0,
329         0, 1, 0
330 };
331
332 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = in[0] * r;
338                 out[1] = in[1] * g;
339                 out[2] = in[2] * b;
340                 out[3] = in[3];
341                 in += 4;
342                 out += 4;
343         }
344 }
345
346 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
347 {
348         int i;
349         for (i = 0;i < verts;i++)
350         {
351                 out[0] = r;
352                 out[1] = g;
353                 out[2] = b;
354                 out[3] = a;
355                 out += 4;
356         }
357 }
358
359 // FIXME: move this to client?
360 void FOG_clear(void)
361 {
362         if (gamemode == GAME_NEHAHRA)
363         {
364                 Cvar_Set("gl_fogenable", "0");
365                 Cvar_Set("gl_fogdensity", "0.2");
366                 Cvar_Set("gl_fogred", "0.3");
367                 Cvar_Set("gl_foggreen", "0.3");
368                 Cvar_Set("gl_fogblue", "0.3");
369         }
370         r_refdef.fog_density = 0;
371         r_refdef.fog_red = 0;
372         r_refdef.fog_green = 0;
373         r_refdef.fog_blue = 0;
374         r_refdef.fog_alpha = 1;
375         r_refdef.fog_start = 0;
376         r_refdef.fog_end = 16384;
377         r_refdef.fog_height = 1<<30;
378         r_refdef.fog_fadedepth = 128;
379         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
380 }
381
382 static void R_BuildBlankTextures(void)
383 {
384         unsigned char data[4];
385         data[2] = 128; // normal X
386         data[1] = 128; // normal Y
387         data[0] = 255; // normal Z
388         data[3] = 255; // height
389         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 255;
391         data[1] = 255;
392         data[2] = 255;
393         data[3] = 255;
394         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395         data[0] = 128;
396         data[1] = 128;
397         data[2] = 128;
398         data[3] = 255;
399         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
400         data[0] = 0;
401         data[1] = 0;
402         data[2] = 0;
403         data[3] = 255;
404         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNoTexture(void)
408 {
409         int x, y;
410         unsigned char pix[16][16][4];
411         // this makes a light grey/dark grey checkerboard texture
412         for (y = 0;y < 16;y++)
413         {
414                 for (x = 0;x < 16;x++)
415                 {
416                         if ((y < 8) ^ (x < 8))
417                         {
418                                 pix[y][x][0] = 128;
419                                 pix[y][x][1] = 128;
420                                 pix[y][x][2] = 128;
421                                 pix[y][x][3] = 255;
422                         }
423                         else
424                         {
425                                 pix[y][x][0] = 64;
426                                 pix[y][x][1] = 64;
427                                 pix[y][x][2] = 64;
428                                 pix[y][x][3] = 255;
429                         }
430                 }
431         }
432         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
433 }
434
435 static void R_BuildWhiteCube(void)
436 {
437         unsigned char data[6*1*1*4];
438         memset(data, 255, sizeof(data));
439         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
440 }
441
442 static void R_BuildNormalizationCube(void)
443 {
444         int x, y, side;
445         vec3_t v;
446         vec_t s, t, intensity;
447 #define NORMSIZE 64
448         unsigned char *data;
449         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
450         for (side = 0;side < 6;side++)
451         {
452                 for (y = 0;y < NORMSIZE;y++)
453                 {
454                         for (x = 0;x < NORMSIZE;x++)
455                         {
456                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
458                                 switch(side)
459                                 {
460                                 default:
461                                 case 0:
462                                         v[0] = 1;
463                                         v[1] = -t;
464                                         v[2] = -s;
465                                         break;
466                                 case 1:
467                                         v[0] = -1;
468                                         v[1] = -t;
469                                         v[2] = s;
470                                         break;
471                                 case 2:
472                                         v[0] = s;
473                                         v[1] = 1;
474                                         v[2] = t;
475                                         break;
476                                 case 3:
477                                         v[0] = s;
478                                         v[1] = -1;
479                                         v[2] = -t;
480                                         break;
481                                 case 4:
482                                         v[0] = s;
483                                         v[1] = -t;
484                                         v[2] = 1;
485                                         break;
486                                 case 5:
487                                         v[0] = -s;
488                                         v[1] = -t;
489                                         v[2] = -1;
490                                         break;
491                                 }
492                                 intensity = 127.0f / sqrt(DotProduct(v, v));
493                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
494                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
495                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
496                                 data[((side*64+y)*64+x)*4+3] = 255;
497                         }
498                 }
499         }
500         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501         Mem_Free(data);
502 }
503
504 static void R_BuildFogTexture(void)
505 {
506         int x, b;
507 #define FOGWIDTH 256
508         unsigned char data1[FOGWIDTH][4];
509         //unsigned char data2[FOGWIDTH][4];
510         double d, r, alpha;
511
512         r_refdef.fogmasktable_start = r_refdef.fog_start;
513         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
514         r_refdef.fogmasktable_range = r_refdef.fogrange;
515         r_refdef.fogmasktable_density = r_refdef.fog_density;
516
517         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
518         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
519         {
520                 d = (x * r - r_refdef.fogmasktable_start);
521                 if(developer_extra.integer)
522                         Con_DPrintf("%f ", d);
523                 d = max(0, d);
524                 if (r_fog_exp2.integer)
525                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
526                 else
527                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
528                 if(developer_extra.integer)
529                         Con_DPrintf(" : %f ", alpha);
530                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
531                 if(developer_extra.integer)
532                         Con_DPrintf(" = %f\n", alpha);
533                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
534         }
535
536         for (x = 0;x < FOGWIDTH;x++)
537         {
538                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
539                 data1[x][0] = b;
540                 data1[x][1] = b;
541                 data1[x][2] = b;
542                 data1[x][3] = 255;
543                 //data2[x][0] = 255 - b;
544                 //data2[x][1] = 255 - b;
545                 //data2[x][2] = 255 - b;
546                 //data2[x][3] = 255;
547         }
548         if (r_texture_fogattenuation)
549         {
550                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
551                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
552         }
553         else
554         {
555                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
556                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
557         }
558 }
559
560 static void R_BuildFogHeightTexture(void)
561 {
562         unsigned char *inpixels;
563         int size;
564         int x;
565         int y;
566         int j;
567         float c[4];
568         float f;
569         inpixels = NULL;
570         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
571         if (r_refdef.fogheighttexturename[0])
572                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
573         if (!inpixels)
574         {
575                 r_refdef.fog_height_tablesize = 0;
576                 if (r_texture_fogheighttexture)
577                         R_FreeTexture(r_texture_fogheighttexture);
578                 r_texture_fogheighttexture = NULL;
579                 if (r_refdef.fog_height_table2d)
580                         Mem_Free(r_refdef.fog_height_table2d);
581                 r_refdef.fog_height_table2d = NULL;
582                 if (r_refdef.fog_height_table1d)
583                         Mem_Free(r_refdef.fog_height_table1d);
584                 r_refdef.fog_height_table1d = NULL;
585                 return;
586         }
587         size = image_width;
588         r_refdef.fog_height_tablesize = size;
589         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
590         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
591         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
592         Mem_Free(inpixels);
593         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
594         // average fog color table accounting for every fog layer between a point
595         // and the camera.  (Note: attenuation is handled separately!)
596         for (y = 0;y < size;y++)
597         {
598                 for (x = 0;x < size;x++)
599                 {
600                         Vector4Clear(c);
601                         f = 0;
602                         if (x < y)
603                         {
604                                 for (j = x;j <= y;j++)
605                                 {
606                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607                                         f++;
608                                 }
609                         }
610                         else
611                         {
612                                 for (j = x;j >= y;j--)
613                                 {
614                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
615                                         f++;
616                                 }
617                         }
618                         f = 1.0f / f;
619                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
621                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
622                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
623                 }
624         }
625         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
626 }
627
628 //=======================================================================================================================================================
629
630 static const char *builtinshaderstrings[] =
631 {
632 #include "shader_glsl.h"
633 0
634 };
635
636 const char *builtinhlslshaderstrings[] =
637 {
638 #include "shader_hlsl.h"
639 0
640 };
641
642 //=======================================================================================================================================================
643
644 typedef struct shaderpermutationinfo_s
645 {
646         const char *pretext;
647         const char *name;
648 }
649 shaderpermutationinfo_t;
650
651 typedef struct shadermodeinfo_s
652 {
653         const char *sourcebasename;
654         const char *extension;
655         const char **builtinshaderstrings;
656         const char *pretext;
657         const char *name;
658         char *filename;
659         char *builtinstring;
660         int builtincrc;
661 }
662 shadermodeinfo_t;
663
664 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
665 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
666 {
667         {"#define USEDIFFUSE\n", " diffuse"},
668         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
669         {"#define USEVIEWTINT\n", " viewtint"},
670         {"#define USECOLORMAPPING\n", " colormapping"},
671         {"#define USESATURATION\n", " saturation"},
672         {"#define USEFOGINSIDE\n", " foginside"},
673         {"#define USEFOGOUTSIDE\n", " fogoutside"},
674         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
675         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
676         {"#define USEGAMMARAMPS\n", " gammaramps"},
677         {"#define USECUBEFILTER\n", " cubefilter"},
678         {"#define USEGLOW\n", " glow"},
679         {"#define USEBLOOM\n", " bloom"},
680         {"#define USESPECULAR\n", " specular"},
681         {"#define USEPOSTPROCESSING\n", " postprocessing"},
682         {"#define USEREFLECTION\n", " reflection"},
683         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
684         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
685         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
686         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
687         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
688         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
689         {"#define USEALPHAKILL\n", " alphakill"},
690         {"#define USEREFLECTCUBE\n", " reflectcube"},
691         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
692         {"#define USEBOUNCEGRID\n", " bouncegrid"},
693         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
694         {"#define USETRIPPY\n", " trippy"},
695         {"#define USEDEPTHRGB\n", " depthrgb"},
696         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
697         {"#define USESKELETAL\n", " skeletal"},
698         {"#define USEOCCLUDE\n", " occlude"}
699 };
700
701 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
702 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
703 {
704         // SHADERLANGUAGE_GLSL
705         {
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
723         },
724         // SHADERLANGUAGE_HLSL
725         {
726                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
727                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
743         },
744 };
745
746 struct r_glsl_permutation_s;
747 typedef struct r_glsl_permutation_s
748 {
749         /// hash lookup data
750         struct r_glsl_permutation_s *hashnext;
751         unsigned int mode;
752         dpuint64 permutation;
753
754         /// indicates if we have tried compiling this permutation already
755         qboolean compiled;
756         /// 0 if compilation failed
757         int program;
758         // texture units assigned to each detected uniform
759         int tex_Texture_First;
760         int tex_Texture_Second;
761         int tex_Texture_GammaRamps;
762         int tex_Texture_Normal;
763         int tex_Texture_Color;
764         int tex_Texture_Gloss;
765         int tex_Texture_Glow;
766         int tex_Texture_SecondaryNormal;
767         int tex_Texture_SecondaryColor;
768         int tex_Texture_SecondaryGloss;
769         int tex_Texture_SecondaryGlow;
770         int tex_Texture_Pants;
771         int tex_Texture_Shirt;
772         int tex_Texture_FogHeightTexture;
773         int tex_Texture_FogMask;
774         int tex_Texture_Lightmap;
775         int tex_Texture_Deluxemap;
776         int tex_Texture_Attenuation;
777         int tex_Texture_Cube;
778         int tex_Texture_Refraction;
779         int tex_Texture_Reflection;
780         int tex_Texture_ShadowMap2D;
781         int tex_Texture_CubeProjection;
782         int tex_Texture_ScreenNormalMap;
783         int tex_Texture_ScreenDiffuse;
784         int tex_Texture_ScreenSpecular;
785         int tex_Texture_ReflectMask;
786         int tex_Texture_ReflectCube;
787         int tex_Texture_BounceGrid;
788         /// locations of detected uniforms in program object, or -1 if not found
789         int loc_Texture_First;
790         int loc_Texture_Second;
791         int loc_Texture_GammaRamps;
792         int loc_Texture_Normal;
793         int loc_Texture_Color;
794         int loc_Texture_Gloss;
795         int loc_Texture_Glow;
796         int loc_Texture_SecondaryNormal;
797         int loc_Texture_SecondaryColor;
798         int loc_Texture_SecondaryGloss;
799         int loc_Texture_SecondaryGlow;
800         int loc_Texture_Pants;
801         int loc_Texture_Shirt;
802         int loc_Texture_FogHeightTexture;
803         int loc_Texture_FogMask;
804         int loc_Texture_Lightmap;
805         int loc_Texture_Deluxemap;
806         int loc_Texture_Attenuation;
807         int loc_Texture_Cube;
808         int loc_Texture_Refraction;
809         int loc_Texture_Reflection;
810         int loc_Texture_ShadowMap2D;
811         int loc_Texture_CubeProjection;
812         int loc_Texture_ScreenNormalMap;
813         int loc_Texture_ScreenDiffuse;
814         int loc_Texture_ScreenSpecular;
815         int loc_Texture_ReflectMask;
816         int loc_Texture_ReflectCube;
817         int loc_Texture_BounceGrid;
818         int loc_Alpha;
819         int loc_BloomBlur_Parameters;
820         int loc_ClientTime;
821         int loc_Color_Ambient;
822         int loc_Color_Diffuse;
823         int loc_Color_Specular;
824         int loc_Color_Glow;
825         int loc_Color_Pants;
826         int loc_Color_Shirt;
827         int loc_DeferredColor_Ambient;
828         int loc_DeferredColor_Diffuse;
829         int loc_DeferredColor_Specular;
830         int loc_DeferredMod_Diffuse;
831         int loc_DeferredMod_Specular;
832         int loc_DistortScaleRefractReflect;
833         int loc_EyePosition;
834         int loc_FogColor;
835         int loc_FogHeightFade;
836         int loc_FogPlane;
837         int loc_FogPlaneViewDist;
838         int loc_FogRangeRecip;
839         int loc_LightColor;
840         int loc_LightDir;
841         int loc_LightPosition;
842         int loc_OffsetMapping_ScaleSteps;
843         int loc_OffsetMapping_LodDistance;
844         int loc_OffsetMapping_Bias;
845         int loc_PixelSize;
846         int loc_ReflectColor;
847         int loc_ReflectFactor;
848         int loc_ReflectOffset;
849         int loc_RefractColor;
850         int loc_Saturation;
851         int loc_ScreenCenterRefractReflect;
852         int loc_ScreenScaleRefractReflect;
853         int loc_ScreenToDepth;
854         int loc_ShadowMap_Parameters;
855         int loc_ShadowMap_TextureScale;
856         int loc_SpecularPower;
857         int loc_Skeletal_Transform12;
858         int loc_UserVec1;
859         int loc_UserVec2;
860         int loc_UserVec3;
861         int loc_UserVec4;
862         int loc_ViewTintColor;
863         int loc_ViewToLight;
864         int loc_ModelToLight;
865         int loc_TexMatrix;
866         int loc_BackgroundTexMatrix;
867         int loc_ModelViewProjectionMatrix;
868         int loc_ModelViewMatrix;
869         int loc_PixelToScreenTexCoord;
870         int loc_ModelToReflectCube;
871         int loc_ShadowMapMatrix;
872         int loc_BloomColorSubtract;
873         int loc_NormalmapScrollBlend;
874         int loc_BounceGridMatrix;
875         int loc_BounceGridIntensity;
876         /// uniform block bindings
877         int ubibind_Skeletal_Transform12_UniformBlock;
878         /// uniform block indices
879         int ubiloc_Skeletal_Transform12_UniformBlock;
880 }
881 r_glsl_permutation_t;
882
883 #define SHADERPERMUTATION_HASHSIZE 256
884
885
886 // non-degradable "lightweight" shader parameters to keep the permutations simpler
887 // these can NOT degrade! only use for simple stuff
888 enum
889 {
890         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
891         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
892         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
893         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
894         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
895         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
896         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
897         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
898         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
899         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
900         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
901         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
902         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
903         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
904 };
905 #define SHADERSTATICPARMS_COUNT 14
906
907 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
908 static int shaderstaticparms_count = 0;
909
910 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
911 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
912
913 extern qboolean r_shadow_shadowmapsampler;
914 extern int r_shadow_shadowmappcf;
915 qboolean R_CompileShader_CheckStaticParms(void)
916 {
917         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
918         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
919         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
920
921         // detect all
922         if (r_glsl_saturation_redcompensate.integer)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
924         if (r_glsl_vertextextureblend_usebothalphas.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
926         if (r_shadow_glossexact.integer)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
928         if (r_glsl_postprocess.integer)
929         {
930                 if (r_glsl_postprocess_uservec1_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
932                 if (r_glsl_postprocess_uservec2_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
934                 if (r_glsl_postprocess_uservec3_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
936                 if (r_glsl_postprocess_uservec4_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
938         }
939         if (r_fxaa.integer)
940                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
941         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
942                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
943
944         if (r_shadow_shadowmapsampler)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
946         if (r_shadow_shadowmappcf > 1)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
948         else if (r_shadow_shadowmappcf)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
950         if (r_celshading.integer)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
952         if (r_celoutlines.integer)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
954
955         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
956 }
957
958 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
959         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
960                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
961         else \
962                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
963 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
964 {
965         shaderstaticparms_count = 0;
966
967         // emit all
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
982 }
983
984 /// information about each possible shader permutation
985 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
986 /// currently selected permutation
987 r_glsl_permutation_t *r_glsl_permutation;
988 /// storage for permutations linked in the hash table
989 memexpandablearray_t r_glsl_permutationarray;
990
991 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
992 {
993         //unsigned int hashdepth = 0;
994         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
995         r_glsl_permutation_t *p;
996         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
997         {
998                 if (p->mode == mode && p->permutation == permutation)
999                 {
1000                         //if (hashdepth > 10)
1001                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1002                         return p;
1003                 }
1004                 //hashdepth++;
1005         }
1006         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1007         p->mode = mode;
1008         p->permutation = permutation;
1009         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1010         r_glsl_permutationhash[mode][hashindex] = p;
1011         //if (hashdepth > 10)
1012         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1013         return p;
1014 }
1015
1016 static char *R_ShaderStrCat(const char **strings)
1017 {
1018         char *string, *s;
1019         const char **p = strings;
1020         const char *t;
1021         size_t len = 0;
1022         for (p = strings;(t = *p);p++)
1023                 len += strlen(t);
1024         len++;
1025         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1026         len = 0;
1027         for (p = strings;(t = *p);p++)
1028         {
1029                 len = strlen(t);
1030                 memcpy(s, t, len);
1031                 s += len;
1032         }
1033         *s = 0;
1034         return string;
1035 }
1036
1037 static char *R_ShaderStrCat(const char **strings);
1038 static void R_InitShaderModeInfo(void)
1039 {
1040         int i, language;
1041         shadermodeinfo_t *modeinfo;
1042         // 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)
1043         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1044         {
1045                 for (i = 0; i < SHADERMODE_COUNT; i++)
1046                 {
1047                         char filename[MAX_QPATH];
1048                         modeinfo = &shadermodeinfo[language][i];
1049                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1050                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1051                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1052                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1053                 }
1054         }
1055 }
1056
1057 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1058 {
1059         char *shaderstring;
1060         // if the mode has no filename we have to return the builtin string
1061         if (builtinonly || !modeinfo->filename)
1062                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1063         // note that FS_LoadFile appends a 0 byte to make it a valid string
1064         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1065         if (shaderstring)
1066         {
1067                 if (printfromdisknotice)
1068                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1069                 return shaderstring;
1070         }
1071         // fall back to builtinstring
1072         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1073 }
1074
1075 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1076 {
1077         int i;
1078         int ubibind;
1079         int sampler;
1080         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1081         char *sourcestring;
1082         char permutationname[256];
1083         int vertstrings_count = 0;
1084         int geomstrings_count = 0;
1085         int fragstrings_count = 0;
1086         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1087         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1088         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089
1090         if (p->compiled)
1091                 return;
1092         p->compiled = true;
1093         p->program = 0;
1094
1095         permutationname[0] = 0;
1096         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1097
1098         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1099
1100         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1101         if(vid.support.glshaderversion >= 140)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1109         }
1110         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1111         else if(vid.support.glshaderversion >= 130)
1112         {
1113                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1114                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1115                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1116                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1117                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1118                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1119         }
1120         // if we can do #version 120, we should (this adds the invariant keyword)
1121         else if(vid.support.glshaderversion >= 120)
1122         {
1123                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1124                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1125                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1126                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1127                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1128                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1129         }
1130         // GLES also adds several things from GLSL120
1131         switch(vid.renderpath)
1132         {
1133         case RENDERPATH_GLES2:
1134                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1135                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1136                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1137                 break;
1138         default:
1139                 break;
1140         }
1141
1142         // the first pretext is which type of shader to compile as
1143         // (later these will all be bound together as a program object)
1144         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1145         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1146         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1147
1148         // the second pretext is the mode (for example a light source)
1149         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1150         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1151         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1152         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1153
1154         // now add all the permutation pretexts
1155         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1156         {
1157                 if (permutation & (1ll<<i))
1158                 {
1159                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1160                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1161                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1162                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1163                 }
1164                 else
1165                 {
1166                         // keep line numbers correct
1167                         vertstrings_list[vertstrings_count++] = "\n";
1168                         geomstrings_list[geomstrings_count++] = "\n";
1169                         fragstrings_list[fragstrings_count++] = "\n";
1170                 }
1171         }
1172
1173         // add static parms
1174         R_CompileShader_AddStaticParms(mode, permutation);
1175         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176         vertstrings_count += shaderstaticparms_count;
1177         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         geomstrings_count += shaderstaticparms_count;
1179         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180         fragstrings_count += shaderstaticparms_count;
1181
1182         // now append the shader text itself
1183         vertstrings_list[vertstrings_count++] = sourcestring;
1184         geomstrings_list[geomstrings_count++] = sourcestring;
1185         fragstrings_list[fragstrings_count++] = sourcestring;
1186
1187         // compile the shader program
1188         if (vertstrings_count + geomstrings_count + fragstrings_count)
1189                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1190         if (p->program)
1191         {
1192                 CHECKGLERROR
1193                 qglUseProgram(p->program);CHECKGLERROR
1194                 // look up all the uniform variable names we care about, so we don't
1195                 // have to look them up every time we set them
1196
1197 #if 0
1198                 // debugging aid
1199                 {
1200                         GLint activeuniformindex = 0;
1201                         GLint numactiveuniforms = 0;
1202                         char uniformname[128];
1203                         GLsizei uniformnamelength = 0;
1204                         GLint uniformsize = 0;
1205                         GLenum uniformtype = 0;
1206                         memset(uniformname, 0, sizeof(uniformname));
1207                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1208                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1209                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1210                         {
1211                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1212                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1213                         }
1214                 }
1215 #endif
1216
1217                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1218                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1219                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1220                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1221                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1222                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1223                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1224                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1225                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1226                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1227                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1228                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1229                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1230                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1231                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1232                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1233                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1234                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1235                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1236                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1237                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1238                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1239                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1240                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1241                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1242                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1243                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1244                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1245                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1246                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1247                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1248                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1249                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1250                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1251                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1252                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1253                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1254                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1255                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1256                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1257                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1258                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1259                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1260                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1261                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1262                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1263                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1264                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1265                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1266                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1267                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1268                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1269                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1270                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1271                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1272                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1273                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1274                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1275                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1276                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1277                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1278                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1279                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1280                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1281                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1282                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1283                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1284                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1285                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1286                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1287                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1288                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1289                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1290                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1291                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1292                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1293                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1294                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1295                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1296                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1297                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1298                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1299                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1300                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1301                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1302                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1303                 // initialize the samplers to refer to the texture units we use
1304                 p->tex_Texture_First = -1;
1305                 p->tex_Texture_Second = -1;
1306                 p->tex_Texture_GammaRamps = -1;
1307                 p->tex_Texture_Normal = -1;
1308                 p->tex_Texture_Color = -1;
1309                 p->tex_Texture_Gloss = -1;
1310                 p->tex_Texture_Glow = -1;
1311                 p->tex_Texture_SecondaryNormal = -1;
1312                 p->tex_Texture_SecondaryColor = -1;
1313                 p->tex_Texture_SecondaryGloss = -1;
1314                 p->tex_Texture_SecondaryGlow = -1;
1315                 p->tex_Texture_Pants = -1;
1316                 p->tex_Texture_Shirt = -1;
1317                 p->tex_Texture_FogHeightTexture = -1;
1318                 p->tex_Texture_FogMask = -1;
1319                 p->tex_Texture_Lightmap = -1;
1320                 p->tex_Texture_Deluxemap = -1;
1321                 p->tex_Texture_Attenuation = -1;
1322                 p->tex_Texture_Cube = -1;
1323                 p->tex_Texture_Refraction = -1;
1324                 p->tex_Texture_Reflection = -1;
1325                 p->tex_Texture_ShadowMap2D = -1;
1326                 p->tex_Texture_CubeProjection = -1;
1327                 p->tex_Texture_ScreenNormalMap = -1;
1328                 p->tex_Texture_ScreenDiffuse = -1;
1329                 p->tex_Texture_ScreenSpecular = -1;
1330                 p->tex_Texture_ReflectMask = -1;
1331                 p->tex_Texture_ReflectCube = -1;
1332                 p->tex_Texture_BounceGrid = -1;
1333                 // bind the texture samplers in use
1334                 sampler = 0;
1335                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1336                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1337                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1338                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1339                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1340                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1341                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1342                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1343                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1344                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1345                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1346                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1347                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1348                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1349                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1350                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1351                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1352                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1353                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1354                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1355                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1356                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1357                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1358                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1359                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1360                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1361                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1362                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1363                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1364                 // get the uniform block indices so we can bind them
1365 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1366                 if (vid.support.arb_uniform_buffer_object)
1367                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1368                 else
1369 #endif
1370                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1371                 // clear the uniform block bindings
1372                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1373                 // bind the uniform blocks in use
1374                 ubibind = 0;
1375 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1376                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1377 #endif
1378                 // we're done compiling and setting up the shader, at least until it is used
1379                 CHECKGLERROR
1380                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1381         }
1382         else
1383                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1384
1385         // free the strings
1386         if (sourcestring)
1387                 Mem_Free(sourcestring);
1388 }
1389
1390 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1391 {
1392         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1393         if (r_glsl_permutation != perm)
1394         {
1395                 r_glsl_permutation = perm;
1396                 if (!r_glsl_permutation->program)
1397                 {
1398                         if (!r_glsl_permutation->compiled)
1399                         {
1400                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1401                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1402                         }
1403                         if (!r_glsl_permutation->program)
1404                         {
1405                                 // remove features until we find a valid permutation
1406                                 int i;
1407                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1408                                 {
1409                                         // reduce i more quickly whenever it would not remove any bits
1410                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1411                                         if (!(permutation & j))
1412                                                 continue;
1413                                         permutation -= j;
1414                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1415                                         if (!r_glsl_permutation->compiled)
1416                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1417                                         if (r_glsl_permutation->program)
1418                                                 break;
1419                                 }
1420                                 if (i >= SHADERPERMUTATION_COUNT)
1421                                 {
1422                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1423                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1424                                         qglUseProgram(0);CHECKGLERROR
1425                                         return; // no bit left to clear, entire mode is broken
1426                                 }
1427                         }
1428                 }
1429                 CHECKGLERROR
1430                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1431         }
1432         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1433         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1434         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1435         CHECKGLERROR
1436 }
1437
1438 #ifdef SUPPORTD3D
1439
1440 #ifdef SUPPORTD3D
1441 #include <d3d9.h>
1442 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1443 extern D3DCAPS9 vid_d3d9caps;
1444 #endif
1445
1446 struct r_hlsl_permutation_s;
1447 typedef struct r_hlsl_permutation_s
1448 {
1449         /// hash lookup data
1450         struct r_hlsl_permutation_s *hashnext;
1451         unsigned int mode;
1452         dpuint64 permutation;
1453
1454         /// indicates if we have tried compiling this permutation already
1455         qboolean compiled;
1456         /// NULL if compilation failed
1457         IDirect3DVertexShader9 *vertexshader;
1458         IDirect3DPixelShader9 *pixelshader;
1459 }
1460 r_hlsl_permutation_t;
1461
1462 typedef enum D3DVSREGISTER_e
1463 {
1464         D3DVSREGISTER_TexMatrix = 0, // float4x4
1465         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1466         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1467         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1468         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1469         D3DVSREGISTER_ModelToLight = 20, // float4x4
1470         D3DVSREGISTER_EyePosition = 24,
1471         D3DVSREGISTER_FogPlane = 25,
1472         D3DVSREGISTER_LightDir = 26,
1473         D3DVSREGISTER_LightPosition = 27,
1474 }
1475 D3DVSREGISTER_t;
1476
1477 typedef enum D3DPSREGISTER_e
1478 {
1479         D3DPSREGISTER_Alpha = 0,
1480         D3DPSREGISTER_BloomBlur_Parameters = 1,
1481         D3DPSREGISTER_ClientTime = 2,
1482         D3DPSREGISTER_Color_Ambient = 3,
1483         D3DPSREGISTER_Color_Diffuse = 4,
1484         D3DPSREGISTER_Color_Specular = 5,
1485         D3DPSREGISTER_Color_Glow = 6,
1486         D3DPSREGISTER_Color_Pants = 7,
1487         D3DPSREGISTER_Color_Shirt = 8,
1488         D3DPSREGISTER_DeferredColor_Ambient = 9,
1489         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1490         D3DPSREGISTER_DeferredColor_Specular = 11,
1491         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1492         D3DPSREGISTER_DeferredMod_Specular = 13,
1493         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1494         D3DPSREGISTER_EyePosition = 15, // unused
1495         D3DPSREGISTER_FogColor = 16,
1496         D3DPSREGISTER_FogHeightFade = 17,
1497         D3DPSREGISTER_FogPlane = 18,
1498         D3DPSREGISTER_FogPlaneViewDist = 19,
1499         D3DPSREGISTER_FogRangeRecip = 20,
1500         D3DPSREGISTER_LightColor = 21,
1501         D3DPSREGISTER_LightDir = 22, // unused
1502         D3DPSREGISTER_LightPosition = 23,
1503         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1504         D3DPSREGISTER_PixelSize = 25,
1505         D3DPSREGISTER_ReflectColor = 26,
1506         D3DPSREGISTER_ReflectFactor = 27,
1507         D3DPSREGISTER_ReflectOffset = 28,
1508         D3DPSREGISTER_RefractColor = 29,
1509         D3DPSREGISTER_Saturation = 30,
1510         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1511         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1512         D3DPSREGISTER_ScreenToDepth = 33,
1513         D3DPSREGISTER_ShadowMap_Parameters = 34,
1514         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1515         D3DPSREGISTER_SpecularPower = 36,
1516         D3DPSREGISTER_UserVec1 = 37,
1517         D3DPSREGISTER_UserVec2 = 38,
1518         D3DPSREGISTER_UserVec3 = 39,
1519         D3DPSREGISTER_UserVec4 = 40,
1520         D3DPSREGISTER_ViewTintColor = 41,
1521         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1522         D3DPSREGISTER_BloomColorSubtract = 43,
1523         D3DPSREGISTER_ViewToLight = 44, // float4x4
1524         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1525         D3DPSREGISTER_NormalmapScrollBlend = 52,
1526         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1527         D3DPSREGISTER_OffsetMapping_Bias = 54,
1528         // next at 54
1529 }
1530 D3DPSREGISTER_t;
1531
1532 /// information about each possible shader permutation
1533 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1534 /// currently selected permutation
1535 r_hlsl_permutation_t *r_hlsl_permutation;
1536 /// storage for permutations linked in the hash table
1537 memexpandablearray_t r_hlsl_permutationarray;
1538
1539 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1540 {
1541         //unsigned int hashdepth = 0;
1542         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1543         r_hlsl_permutation_t *p;
1544         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1545         {
1546                 if (p->mode == mode && p->permutation == permutation)
1547                 {
1548                         //if (hashdepth > 10)
1549                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1550                         return p;
1551                 }
1552                 //hashdepth++;
1553         }
1554         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1555         p->mode = mode;
1556         p->permutation = permutation;
1557         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1558         r_hlsl_permutationhash[mode][hashindex] = p;
1559         //if (hashdepth > 10)
1560         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1561         return p;
1562 }
1563
1564 #include <d3dx9.h>
1565 //#include <d3dx9shader.h>
1566 //#include <d3dx9mesh.h>
1567
1568 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1569 {
1570         DWORD *vsbin = NULL;
1571         DWORD *psbin = NULL;
1572         fs_offset_t vsbinsize;
1573         fs_offset_t psbinsize;
1574 //      IDirect3DVertexShader9 *vs = NULL;
1575 //      IDirect3DPixelShader9 *ps = NULL;
1576         ID3DXBuffer *vslog = NULL;
1577         ID3DXBuffer *vsbuffer = NULL;
1578         ID3DXConstantTable *vsconstanttable = NULL;
1579         ID3DXBuffer *pslog = NULL;
1580         ID3DXBuffer *psbuffer = NULL;
1581         ID3DXConstantTable *psconstanttable = NULL;
1582         int vsresult = 0;
1583         int psresult = 0;
1584         char temp[MAX_INPUTLINE];
1585         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1586         char vabuf[1024];
1587         qboolean debugshader = gl_paranoid.integer != 0;
1588         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1589         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1590         if (!debugshader)
1591         {
1592                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1593                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1594         }
1595         if ((!vsbin && vertstring) || (!psbin && fragstring))
1596         {
1597                 const char* dllnames_d3dx9 [] =
1598                 {
1599                         "d3dx9_43.dll",
1600                         "d3dx9_42.dll",
1601                         "d3dx9_41.dll",
1602                         "d3dx9_40.dll",
1603                         "d3dx9_39.dll",
1604                         "d3dx9_38.dll",
1605                         "d3dx9_37.dll",
1606                         "d3dx9_36.dll",
1607                         "d3dx9_35.dll",
1608                         "d3dx9_34.dll",
1609                         "d3dx9_33.dll",
1610                         "d3dx9_32.dll",
1611                         "d3dx9_31.dll",
1612                         "d3dx9_30.dll",
1613                         "d3dx9_29.dll",
1614                         "d3dx9_28.dll",
1615                         "d3dx9_27.dll",
1616                         "d3dx9_26.dll",
1617                         "d3dx9_25.dll",
1618                         "d3dx9_24.dll",
1619                         NULL
1620                 };
1621                 dllhandle_t d3dx9_dll = NULL;
1622                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1624                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625                 dllfunction_t d3dx9_dllfuncs[] =
1626                 {
1627                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1628                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1629                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1630                         {NULL, NULL}
1631                 };
1632                 // 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...
1633 #ifndef ID3DXBuffer_GetBufferPointer
1634 #if !defined(__cplusplus) || defined(CINTERFACE)
1635 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1636 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1637 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1638 #else
1639 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1640 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1641 #define ID3DXBuffer_Release(p)            (p)->Release()
1642 #endif
1643 #endif
1644                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1645                 {
1646                         DWORD shaderflags = 0;
1647                         if (debugshader)
1648                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1649                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1650                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1651                         if (vertstring && vertstring[0])
1652                         {
1653                                 if (debugshader)
1654                                 {
1655                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1656                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1657                                 }
1658                                 else
1659                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1660                                 if (vsbuffer)
1661                                 {
1662                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1663                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1664                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1665                                         ID3DXBuffer_Release(vsbuffer);
1666                                 }
1667                                 if (vslog)
1668                                 {
1669                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1670                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1671                                         ID3DXBuffer_Release(vslog);
1672                                 }
1673                         }
1674                         if (fragstring && fragstring[0])
1675                         {
1676                                 if (debugshader)
1677                                 {
1678                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1679                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1680                                 }
1681                                 else
1682                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1683                                 if (psbuffer)
1684                                 {
1685                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1686                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1687                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1688                                         ID3DXBuffer_Release(psbuffer);
1689                                 }
1690                                 if (pslog)
1691                                 {
1692                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1693                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1694                                         ID3DXBuffer_Release(pslog);
1695                                 }
1696                         }
1697                         Sys_UnloadLibrary(&d3dx9_dll);
1698                 }
1699                 else
1700                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1701         }
1702         if (vsbin && psbin)
1703         {
1704                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1705                 if (FAILED(vsresult))
1706                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1707                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1708                 if (FAILED(psresult))
1709                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1710         }
1711         // free the shader data
1712         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1713         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1714 }
1715
1716 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1717 {
1718         int i;
1719         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1720         int vertstring_length = 0;
1721         int geomstring_length = 0;
1722         int fragstring_length = 0;
1723         char *t;
1724         char *sourcestring;
1725         char *vertstring, *geomstring, *fragstring;
1726         char permutationname[256];
1727         char cachename[256];
1728         int vertstrings_count = 0;
1729         int geomstrings_count = 0;
1730         int fragstrings_count = 0;
1731         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1732         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1733         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734
1735         if (p->compiled)
1736                 return;
1737         p->compiled = true;
1738         p->vertexshader = NULL;
1739         p->pixelshader = NULL;
1740
1741         permutationname[0] = 0;
1742         cachename[0] = 0;
1743         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1744
1745         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1746         strlcat(cachename, "hlsl/", sizeof(cachename));
1747
1748         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1749         vertstrings_count = 0;
1750         geomstrings_count = 0;
1751         fragstrings_count = 0;
1752         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1753         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1754         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1755
1756         // the first pretext is which type of shader to compile as
1757         // (later these will all be bound together as a program object)
1758         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1759         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1760         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1761
1762         // the second pretext is the mode (for example a light source)
1763         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1764         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1765         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1766         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1767         strlcat(cachename, modeinfo->name, sizeof(cachename));
1768
1769         // now add all the permutation pretexts
1770         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1771         {
1772                 if (permutation & (1ll<<i))
1773                 {
1774                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1775                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1776                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1777                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1778                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1779                 }
1780                 else
1781                 {
1782                         // keep line numbers correct
1783                         vertstrings_list[vertstrings_count++] = "\n";
1784                         geomstrings_list[geomstrings_count++] = "\n";
1785                         fragstrings_list[fragstrings_count++] = "\n";
1786                 }
1787         }
1788
1789         // add static parms
1790         R_CompileShader_AddStaticParms(mode, permutation);
1791         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792         vertstrings_count += shaderstaticparms_count;
1793         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         geomstrings_count += shaderstaticparms_count;
1795         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796         fragstrings_count += shaderstaticparms_count;
1797
1798         // replace spaces in the cachename with _ characters
1799         for (i = 0;cachename[i];i++)
1800                 if (cachename[i] == ' ')
1801                         cachename[i] = '_';
1802
1803         // now append the shader text itself
1804         vertstrings_list[vertstrings_count++] = sourcestring;
1805         geomstrings_list[geomstrings_count++] = sourcestring;
1806         fragstrings_list[fragstrings_count++] = sourcestring;
1807
1808         vertstring_length = 0;
1809         for (i = 0;i < vertstrings_count;i++)
1810                 vertstring_length += (int)strlen(vertstrings_list[i]);
1811         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1812         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1813                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1814
1815         geomstring_length = 0;
1816         for (i = 0;i < geomstrings_count;i++)
1817                 geomstring_length += (int)strlen(geomstrings_list[i]);
1818         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1819         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1820                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1821
1822         fragstring_length = 0;
1823         for (i = 0;i < fragstrings_count;i++)
1824                 fragstring_length += (int)strlen(fragstrings_list[i]);
1825         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1826         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1827                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1828
1829         // try to load the cached shader, or generate one
1830         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1831
1832         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1833                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1834         else
1835                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1836
1837         // free the strings
1838         if (vertstring)
1839                 Mem_Free(vertstring);
1840         if (geomstring)
1841                 Mem_Free(geomstring);
1842         if (fragstring)
1843                 Mem_Free(fragstring);
1844         if (sourcestring)
1845                 Mem_Free(sourcestring);
1846 }
1847
1848 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1849 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1850 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);}
1851 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);}
1852 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);}
1853 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);}
1854
1855 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 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);}
1858 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);}
1859 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);}
1860 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);}
1861
1862 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1863 {
1864         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1865         if (r_hlsl_permutation != perm)
1866         {
1867                 r_hlsl_permutation = perm;
1868                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1869                 {
1870                         if (!r_hlsl_permutation->compiled)
1871                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1872                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1873                         {
1874                                 // remove features until we find a valid permutation
1875                                 int i;
1876                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1877                                 {
1878                                         // reduce i more quickly whenever it would not remove any bits
1879                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1880                                         if (!(permutation & j))
1881                                                 continue;
1882                                         permutation -= j;
1883                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1884                                         if (!r_hlsl_permutation->compiled)
1885                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1886                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1887                                                 break;
1888                                 }
1889                                 if (i >= SHADERPERMUTATION_COUNT)
1890                                 {
1891                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1892                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1893                                         return; // no bit left to clear, entire mode is broken
1894                                 }
1895                         }
1896                 }
1897                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1898                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1899         }
1900         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1901         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1902         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1903 }
1904 #endif
1905
1906 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1907 {
1908         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1909         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1910         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1911         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1912 }
1913
1914 void R_GLSL_Restart_f(void)
1915 {
1916         unsigned int i, limit;
1917         switch(vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 {
1922                         r_hlsl_permutation_t *p;
1923                         r_hlsl_permutation = NULL;
1924                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1925                         for (i = 0;i < limit;i++)
1926                         {
1927                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1928                                 {
1929                                         if (p->vertexshader)
1930                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1931                                         if (p->pixelshader)
1932                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1933                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1934                                 }
1935                         }
1936                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1937                 }
1938 #endif
1939                 break;
1940         case RENDERPATH_D3D10:
1941                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942                 break;
1943         case RENDERPATH_D3D11:
1944                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_GL20:
1947         case RENDERPATH_GLES2:
1948                 {
1949                         r_glsl_permutation_t *p;
1950                         r_glsl_permutation = NULL;
1951                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1952                         for (i = 0;i < limit;i++)
1953                         {
1954                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1955                                 {
1956                                         GL_Backend_FreeProgram(p->program);
1957                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1958                                 }
1959                         }
1960                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1961                 }
1962                 break;
1963         case RENDERPATH_GL11:
1964         case RENDERPATH_GL13:
1965         case RENDERPATH_GLES1:
1966                 break;
1967         case RENDERPATH_SOFT:
1968                 break;
1969         }
1970 }
1971
1972 static void R_GLSL_DumpShader_f(void)
1973 {
1974         int i, language, mode, dupe;
1975         char *text;
1976         shadermodeinfo_t *modeinfo;
1977         qfile_t *file;
1978
1979         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1980         {
1981                 modeinfo = shadermodeinfo[language];
1982                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1983                 {
1984                         // don't dump the same file multiple times (most or all shaders come from the same file)
1985                         for (dupe = mode - 1;dupe >= 0;dupe--)
1986                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1987                                         break;
1988                         if (dupe >= 0)
1989                                 continue;
1990                         text = modeinfo[mode].builtinstring;
1991                         if (!text)
1992                                 continue;
1993                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1994                         if (file)
1995                         {
1996                                 FS_Print(file, "/* The engine may define the following macros:\n");
1997                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1998                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1999                                         FS_Print(file, modeinfo[i].pretext);
2000                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2001                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2002                                 FS_Print(file, "*/\n");
2003                                 FS_Print(file, text);
2004                                 FS_Close(file);
2005                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2006                         }
2007                         else
2008                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2009                 }
2010         }
2011 }
2012
2013 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2014 {
2015         dpuint64 permutation = 0;
2016         if (r_trippy.integer && !notrippy)
2017                 permutation |= SHADERPERMUTATION_TRIPPY;
2018         permutation |= SHADERPERMUTATION_VIEWTINT;
2019         if (first)
2020                 permutation |= SHADERPERMUTATION_DIFFUSE;
2021         if (second)
2022                 permutation |= SHADERPERMUTATION_SPECULAR;
2023         if (texturemode == GL_MODULATE)
2024                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2025         else if (texturemode == GL_ADD)
2026                 permutation |= SHADERPERMUTATION_GLOW;
2027         else if (texturemode == GL_DECAL)
2028                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2029         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2030                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2031         if (suppresstexalpha)
2032                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2033         if (!second)
2034                 texturemode = GL_MODULATE;
2035         if (vid.allowalphatocoverage)
2036                 GL_AlphaToCoverage(false);
2037         switch (vid.renderpath)
2038         {
2039         case RENDERPATH_D3D9:
2040 #ifdef SUPPORTD3D
2041                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2042                 R_Mesh_TexBind(GL20TU_FIRST , first );
2043                 R_Mesh_TexBind(GL20TU_SECOND, second);
2044                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2045                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2046 #endif
2047                 break;
2048         case RENDERPATH_D3D10:
2049                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2050                 break;
2051         case RENDERPATH_D3D11:
2052                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2053                 break;
2054         case RENDERPATH_GL20:
2055         case RENDERPATH_GLES2:
2056                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2057                 if (r_glsl_permutation->tex_Texture_First >= 0)
2058                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2059                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2061                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2062                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2063                 break;
2064         case RENDERPATH_GL13:
2065         case RENDERPATH_GLES1:
2066                 R_Mesh_TexBind(0, first );
2067                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2068                 R_Mesh_TexMatrix(0, NULL);
2069                 R_Mesh_TexBind(1, second);
2070                 if (second)
2071                 {
2072                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2073                         R_Mesh_TexMatrix(1, NULL);
2074                 }
2075                 break;
2076         case RENDERPATH_GL11:
2077                 R_Mesh_TexBind(0, first );
2078                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2079                 R_Mesh_TexMatrix(0, NULL);
2080                 break;
2081         case RENDERPATH_SOFT:
2082                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2083                 R_Mesh_TexBind(GL20TU_FIRST , first );
2084                 R_Mesh_TexBind(GL20TU_SECOND, second);
2085                 break;
2086         }
2087 }
2088
2089 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2090 {
2091         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2092 }
2093
2094 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2095 {
2096         dpuint64 permutation = 0;
2097         if (r_trippy.integer && !notrippy)
2098                 permutation |= SHADERPERMUTATION_TRIPPY;
2099         if (depthrgb)
2100                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2101         if (skeletal)
2102                 permutation |= SHADERPERMUTATION_SKELETAL;
2103
2104         if (vid.allowalphatocoverage)
2105                 GL_AlphaToCoverage(false);
2106         switch (vid.renderpath)
2107         {
2108         case RENDERPATH_D3D9:
2109 #ifdef SUPPORTD3D
2110                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2111 #endif
2112                 break;
2113         case RENDERPATH_D3D10:
2114                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2115                 break;
2116         case RENDERPATH_D3D11:
2117                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2118                 break;
2119         case RENDERPATH_GL20:
2120         case RENDERPATH_GLES2:
2121                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2122 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2123                 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);
2124 #endif
2125                 break;
2126         case RENDERPATH_GL13:
2127         case RENDERPATH_GLES1:
2128                 R_Mesh_TexBind(0, 0);
2129                 R_Mesh_TexBind(1, 0);
2130                 break;
2131         case RENDERPATH_GL11:
2132                 R_Mesh_TexBind(0, 0);
2133                 break;
2134         case RENDERPATH_SOFT:
2135                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2136                 break;
2137         }
2138 }
2139
2140 #define BLENDFUNC_ALLOWS_COLORMOD      1
2141 #define BLENDFUNC_ALLOWS_FOG           2
2142 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2143 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2144 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2145 static int R_BlendFuncFlags(int src, int dst)
2146 {
2147         int r = 0;
2148
2149         // a blendfunc allows colormod if:
2150         // a) it can never keep the destination pixel invariant, or
2151         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2152         // this is to prevent unintended side effects from colormod
2153
2154         // a blendfunc allows fog if:
2155         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2156         // this is to prevent unintended side effects from fog
2157
2158         // these checks are the output of fogeval.pl
2159
2160         r |= BLENDFUNC_ALLOWS_COLORMOD;
2161         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2162         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2163         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2165         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2169         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2170         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2171         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2172         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2173         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2174         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2176         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2179         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2180         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2181         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182
2183         return r;
2184 }
2185
2186 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)
2187 {
2188         // select a permutation of the lighting shader appropriate to this
2189         // combination of texture, entity, light source, and fogging, only use the
2190         // minimum features necessary to avoid wasting rendering time in the
2191         // fragment shader on features that are not being used
2192         dpuint64 permutation = 0;
2193         unsigned int mode = 0;
2194         int blendfuncflags;
2195         texture_t *t = rsurface.texture;
2196         float m16f[16];
2197         matrix4x4_t tempmatrix;
2198         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2199         if (r_trippy.integer && !notrippy)
2200                 permutation |= SHADERPERMUTATION_TRIPPY;
2201         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2202                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2203         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2204                 permutation |= SHADERPERMUTATION_OCCLUDE;
2205         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2206                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207         if (rsurfacepass == RSURFPASS_BACKGROUND)
2208         {
2209                 // distorted background
2210                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2211                 {
2212                         mode = SHADERMODE_WATER;
2213                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2216                         {
2217                                 // this is the right thing to do for wateralpha
2218                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2219                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2220                         }
2221                         else
2222                         {
2223                                 // this is the right thing to do for entity alpha
2224                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2226                         }
2227                 }
2228                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2229                 {
2230                         mode = SHADERMODE_REFRACTION;
2231                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2235                 }
2236                 else
2237                 {
2238                         mode = SHADERMODE_GENERIC;
2239                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242                 }
2243                 if (vid.allowalphatocoverage)
2244                         GL_AlphaToCoverage(false);
2245         }
2246         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2247         {
2248                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2249                 {
2250                         switch(t->offsetmapping)
2251                         {
2252                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255                         case OFFSETMAPPING_OFF: break;
2256                         }
2257                 }
2258                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260                 // normalmap (deferred prepass), may use alpha test on diffuse
2261                 mode = SHADERMODE_DEFERREDGEOMETRY;
2262                 GL_BlendFunc(GL_ONE, GL_ZERO);
2263                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264                 if (vid.allowalphatocoverage)
2265                         GL_AlphaToCoverage(false);
2266         }
2267         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2268         {
2269                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2270                 {
2271                         switch(t->offsetmapping)
2272                         {
2273                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276                         case OFFSETMAPPING_OFF: break;
2277                         }
2278                 }
2279                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2283                 // light source
2284                 mode = SHADERMODE_LIGHTSOURCE;
2285                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2287                 if (VectorLength2(rtlightdiffuse) > 0)
2288                         permutation |= SHADERPERMUTATION_DIFFUSE;
2289                 if (VectorLength2(rtlightspecular) > 0)
2290                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291                 if (r_refdef.fogenabled)
2292                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293                 if (t->colormapping)
2294                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2295                 if (r_shadow_usingshadowmap2d)
2296                 {
2297                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298                         if(r_shadow_shadowmapvsdct)
2299                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2300
2301                         if (r_shadow_shadowmap2ddepthbuffer)
2302                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2303                 }
2304                 if (t->reflectmasktexture)
2305                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308                 if (vid.allowalphatocoverage)
2309                         GL_AlphaToCoverage(false);
2310         }
2311         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2312         {
2313                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2314                 {
2315                         switch(t->offsetmapping)
2316                         {
2317                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320                         case OFFSETMAPPING_OFF: break;
2321                         }
2322                 }
2323                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327                 // directional model lighting
2328                 mode = SHADERMODE_LIGHTDIRECTION;
2329                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2330                         permutation |= SHADERPERMUTATION_GLOW;
2331                 if (VectorLength2(t->render_modellight_diffuse))
2332                         permutation |= SHADERPERMUTATION_DIFFUSE;
2333                 if (VectorLength2(t->render_modellight_specular) > 0)
2334                         permutation |= SHADERPERMUTATION_SPECULAR;
2335                 if (r_refdef.fogenabled)
2336                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337                 if (t->colormapping)
2338                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2339                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2340                 {
2341                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2343
2344                         if (r_shadow_shadowmap2ddepthbuffer)
2345                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2346                 }
2347                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2348                         permutation |= SHADERPERMUTATION_REFLECTION;
2349                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2350                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2351                 if (t->reflectmasktexture)
2352                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2353                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2354                 {
2355                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2356                         if (r_shadow_bouncegrid_state.directional)
2357                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2358                 }
2359                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2360                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2361                 // when using alphatocoverage, we don't need alphakill
2362                 if (vid.allowalphatocoverage)
2363                 {
2364                         if (r_transparent_alphatocoverage.integer)
2365                         {
2366                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2367                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2368                         }
2369                         else
2370                                 GL_AlphaToCoverage(false);
2371                 }
2372         }
2373         else
2374         {
2375                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2376                 {
2377                         switch(t->offsetmapping)
2378                         {
2379                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2380                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2381                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2382                         case OFFSETMAPPING_OFF: break;
2383                         }
2384                 }
2385                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2386                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2387                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2388                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2389                 // lightmapped wall
2390                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2391                         permutation |= SHADERPERMUTATION_GLOW;
2392                 if (r_refdef.fogenabled)
2393                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2394                 if (t->colormapping)
2395                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2396                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2397                 {
2398                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2399                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2400
2401                         if (r_shadow_shadowmap2ddepthbuffer)
2402                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2403                 }
2404                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2405                         permutation |= SHADERPERMUTATION_REFLECTION;
2406                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2407                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2408                 if (t->reflectmasktexture)
2409                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2410                 if (FAKELIGHT_ENABLED)
2411                 {
2412                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2413                         mode = SHADERMODE_FAKELIGHT;
2414                         permutation |= SHADERPERMUTATION_DIFFUSE;
2415                         if (VectorLength2(t->render_lightmap_specular) > 0)
2416                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2417                 }
2418                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2419                 {
2420                         // deluxemapping (light direction texture)
2421                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2422                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2423                         else
2424                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2425                         permutation |= SHADERPERMUTATION_DIFFUSE;
2426                         if (VectorLength2(t->render_lightmap_specular) > 0)
2427                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2428                 }
2429                 else if (r_glsl_deluxemapping.integer >= 2)
2430                 {
2431                         // fake deluxemapping (uniform light direction in tangentspace)
2432                         if (rsurface.uselightmaptexture)
2433                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2434                         else
2435                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2436                         permutation |= SHADERPERMUTATION_DIFFUSE;
2437                         if (VectorLength2(t->render_lightmap_specular) > 0)
2438                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2439                 }
2440                 else if (rsurface.uselightmaptexture)
2441                 {
2442                         // ordinary lightmapping (q1bsp, q3bsp)
2443                         mode = SHADERMODE_LIGHTMAP;
2444                 }
2445                 else
2446                 {
2447                         // ordinary vertex coloring (q3bsp)
2448                         mode = SHADERMODE_VERTEXCOLOR;
2449                 }
2450                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2451                 {
2452                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2453                         if (r_shadow_bouncegrid_state.directional)
2454                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2455                 }
2456                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2457                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2458                 // when using alphatocoverage, we don't need alphakill
2459                 if (vid.allowalphatocoverage)
2460                 {
2461                         if (r_transparent_alphatocoverage.integer)
2462                         {
2463                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2464                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2465                         }
2466                         else
2467                                 GL_AlphaToCoverage(false);
2468                 }
2469         }
2470         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2471                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2472         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2473                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2474         switch(vid.renderpath)
2475         {
2476         case RENDERPATH_D3D9:
2477 #ifdef SUPPORTD3D
2478                 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);
2479                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2480                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2481                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2482                 if (mode == SHADERMODE_LIGHTSOURCE)
2483                 {
2484                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2485                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2486                 }
2487                 else
2488                 {
2489                         if (mode == SHADERMODE_LIGHTDIRECTION)
2490                         {
2491                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2492                         }
2493                 }
2494                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2495                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2496                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2497                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2498                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2499
2500                 if (mode == SHADERMODE_LIGHTSOURCE)
2501                 {
2502                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2503                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2504                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2505                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2506                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2507
2508                         // additive passes are only darkened by fog, not tinted
2509                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2510                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2511                 }
2512                 else
2513                 {
2514                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2515                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2516                         if (mode == SHADERMODE_FLATCOLOR)
2517                         {
2518                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2519                         }
2520                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2521                         {
2522                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2523                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2524                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2525                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2526                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2527                         }
2528                         else
2529                         {
2530                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2531                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2532                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2533                         }
2534                         // additive passes are only darkened by fog, not tinted
2535                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2536                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2537                         else
2538                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2539                         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);
2540                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2541                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2542                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2543                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2544                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2545                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2546                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2547                         if (mode == SHADERMODE_WATER)
2548                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2549                 }
2550                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2551                 {
2552                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2553                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2554                 }
2555                 else
2556                 {
2557                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2558                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2559                 }
2560                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2561                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2562                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2563                 if (t->pantstexture)
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2565                 else
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2567                 if (t->shirttexture)
2568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2569                 else
2570                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2571                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2572                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2573                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2574                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2575                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2576                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2577                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2578                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2579                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2580                         );
2581                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2582                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2583                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2584                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2585
2586                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2587                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2588                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2589                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2590                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2591                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2592                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2593                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2594                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2595                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2596                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2597                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2598                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2599                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2600                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2601                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2602                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2603                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2604                 {
2605                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2606                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2607                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2608                 }
2609                 else
2610                 {
2611                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2612                 }
2613 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2614                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2615                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2616                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2617                 {
2618                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2619                         if (rsurface.rtlight)
2620                         {
2621                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2622                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2623                         }
2624                 }
2625 #endif
2626                 break;
2627         case RENDERPATH_D3D10:
2628                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2629                 break;
2630         case RENDERPATH_D3D11:
2631                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2632                 break;
2633         case RENDERPATH_GL20:
2634         case RENDERPATH_GLES2:
2635                 if (!vid.useinterleavedarrays)
2636                 {
2637                         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);
2638                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2639                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2640                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2641                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2642                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2643                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2644                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2645                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2646                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2647                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2648                 }
2649                 else
2650                 {
2651                         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);
2652                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2653                 }
2654                 // this has to be after RSurf_PrepareVerticesForBatch
2655                 if (rsurface.batchskeletaltransform3x4buffer)
2656                         permutation |= SHADERPERMUTATION_SKELETAL;
2657                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2658 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2659                 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);
2660 #endif
2661                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2662                 if (mode == SHADERMODE_LIGHTSOURCE)
2663                 {
2664                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2665                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2666                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2667                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2668                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2669                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2670         
2671                         // additive passes are only darkened by fog, not tinted
2672                         if (r_glsl_permutation->loc_FogColor >= 0)
2673                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2674                         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);
2675                 }
2676                 else
2677                 {
2678                         if (mode == SHADERMODE_FLATCOLOR)
2679                         {
2680                                 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]);
2681                         }
2682                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2683                         {
2684                                 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]);
2685                                 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]);
2686                                 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]);
2687                                 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]);
2688                                 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]);
2689                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2690                                 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]);
2691                         }
2692                         else
2693                         {
2694                                 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]);
2695                                 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]);
2696                                 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]);
2697                                 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]);
2698                                 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]);
2699                         }
2700                         // additive passes are only darkened by fog, not tinted
2701                         if (r_glsl_permutation->loc_FogColor >= 0)
2702                         {
2703                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2704                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2705                                 else
2706                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2707                         }
2708                         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);
2709                         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]);
2710                         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]);
2711                         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);
2712                         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);
2713                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2714                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2715                         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);
2716                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2717                 }
2718                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2719                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2720                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2721                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2722                 {
2723                         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]);
2724                         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]);
2725                 }
2726                 else
2727                 {
2728                         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]);
2729                         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]);
2730                 }
2731
2732                 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]);
2733                 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));
2734                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2735                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2736                 {
2737                         if (t->pantstexture)
2738                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2739                         else
2740                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2741                 }
2742                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2743                 {
2744                         if (t->shirttexture)
2745                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2746                         else
2747                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2748                 }
2749                 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]);
2750                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2751                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2752                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2753                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2754                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2755                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2756                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2757                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2758                         );
2759                 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);
2760                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2761                 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]);
2762                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2763                 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);}
2764                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2765
2766                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2767                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2768                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2769                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2770                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2771                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2772                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2773                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2774                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2775                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2777                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2778                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2779                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2780                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2781                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2782                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2783                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2784                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2785                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2786                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2787                 {
2788                         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);
2789                         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);
2790                         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);
2791                 }
2792                 else
2793                 {
2794                         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);
2795                 }
2796                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2797                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2798                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2799                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2800                 {
2801                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2802                         if (rsurface.rtlight)
2803                         {
2804                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2805                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2806                         }
2807                 }
2808                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2809                 CHECKGLERROR
2810                 break;
2811         case RENDERPATH_GL11:
2812         case RENDERPATH_GL13:
2813         case RENDERPATH_GLES1:
2814                 break;
2815         case RENDERPATH_SOFT:
2816                 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);
2817                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2818                 R_SetupShader_SetPermutationSoft(mode, permutation);
2819                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2820                 if (mode == SHADERMODE_LIGHTSOURCE)
2821                 {
2822                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2823                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2824                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2825                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2826                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2828         
2829                         // additive passes are only darkened by fog, not tinted
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2831                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2832                 }
2833                 else
2834                 {
2835                         if (mode == SHADERMODE_FLATCOLOR)
2836                         {
2837                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2838                         }
2839                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2840                         {
2841                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2842                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2844                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2846                         }
2847                         else
2848                         {
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2852                         }
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2855                         // additive passes are only darkened by fog, not tinted
2856                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2858                         else
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2860                         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);
2861                         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]);
2862                         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]);
2863                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2864                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2866                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2867                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2868                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2869                 }
2870                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2871                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2872                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2873                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2874                 {
2875                         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]);
2876                         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]);
2877                 }
2878                 else
2879                 {
2880                         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]);
2881                         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]);
2882                 }
2883
2884                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2885                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2886                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2887                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2888                 {
2889                         if (t->pantstexture)
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2891                         else
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2893                 }
2894                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2895                 {
2896                         if (t->shirttexture)
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2898                         else
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2900                 }
2901                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2903                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2904                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2905                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2906                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2907                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2908                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2909                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2910                         );
2911                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2912                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2913                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2915
2916                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2917                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2918                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2919                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2920                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2921                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2922                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2923                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2924                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2925                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2926                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2927                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2928                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2929                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2930                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2931                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2932                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2933                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2934                 {
2935                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2936                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2937                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2938                 }
2939                 else
2940                 {
2941                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2942                 }
2943 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2944                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2945                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2946                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2947                 {
2948                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2949                         if (rsurface.rtlight)
2950                         {
2951                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2952                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2953                         }
2954                 }
2955                 break;
2956         }
2957 }
2958
2959 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2960 {
2961         // select a permutation of the lighting shader appropriate to this
2962         // combination of texture, entity, light source, and fogging, only use the
2963         // minimum features necessary to avoid wasting rendering time in the
2964         // fragment shader on features that are not being used
2965         dpuint64 permutation = 0;
2966         unsigned int mode = 0;
2967         const float *lightcolorbase = rtlight->currentcolor;
2968         float ambientscale = rtlight->ambientscale;
2969         float diffusescale = rtlight->diffusescale;
2970         float specularscale = rtlight->specularscale;
2971         // this is the location of the light in view space
2972         vec3_t viewlightorigin;
2973         // this transforms from view space (camera) to light space (cubemap)
2974         matrix4x4_t viewtolight;
2975         matrix4x4_t lighttoview;
2976         float viewtolight16f[16];
2977         // light source
2978         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2979         if (rtlight->currentcubemap != r_texture_whitecube)
2980                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2981         if (diffusescale > 0)
2982                 permutation |= SHADERPERMUTATION_DIFFUSE;
2983         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2984                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2985         if (r_shadow_usingshadowmap2d)
2986         {
2987                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2988                 if (r_shadow_shadowmapvsdct)
2989                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2990
2991                 if (r_shadow_shadowmap2ddepthbuffer)
2992                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2993         }
2994         if (vid.allowalphatocoverage)
2995                 GL_AlphaToCoverage(false);
2996         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2997         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2998         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2999         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3000         switch(vid.renderpath)
3001         {
3002         case RENDERPATH_D3D9:
3003 #ifdef SUPPORTD3D
3004                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3005                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3006                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3007                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3008                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3010                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3011                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3012                 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);
3013                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3014                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3015
3016                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3017                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3018                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3019                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3020                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3021 #endif
3022                 break;
3023         case RENDERPATH_D3D10:
3024                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3025                 break;
3026         case RENDERPATH_D3D11:
3027                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028                 break;
3029         case RENDERPATH_GL20:
3030         case RENDERPATH_GLES2:
3031                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3032                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3034                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3035                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3036                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3037                 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]);
3038                 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]);
3039                 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);
3040                 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]);
3041                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3042
3043                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3044                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3045                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3046                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3047                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3048                 break;
3049         case RENDERPATH_GL11:
3050         case RENDERPATH_GL13:
3051         case RENDERPATH_GLES1:
3052                 break;
3053         case RENDERPATH_SOFT:
3054                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3055                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3056                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3057                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3058                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3059                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3060                 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]);
3061                 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]);
3062                 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);
3063                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3064                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3065
3066                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3067                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3068                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3069                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3070                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3071                 break;
3072         }
3073 }
3074
3075 #define SKINFRAME_HASH 1024
3076
3077 typedef struct
3078 {
3079         unsigned int loadsequence; // incremented each level change
3080         memexpandablearray_t array;
3081         skinframe_t *hash[SKINFRAME_HASH];
3082 }
3083 r_skinframe_t;
3084 r_skinframe_t r_skinframe;
3085
3086 void R_SkinFrame_PrepareForPurge(void)
3087 {
3088         r_skinframe.loadsequence++;
3089         // wrap it without hitting zero
3090         if (r_skinframe.loadsequence >= 200)
3091                 r_skinframe.loadsequence = 1;
3092 }
3093
3094 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3095 {
3096         if (!skinframe)
3097                 return;
3098         // mark the skinframe as used for the purging code
3099         skinframe->loadsequence = r_skinframe.loadsequence;
3100 }
3101
3102 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3103 {
3104         if (s->merged == s->base)
3105                 s->merged = NULL;
3106         R_PurgeTexture(s->stain); s->stain = NULL;
3107         R_PurgeTexture(s->merged); s->merged = NULL;
3108         R_PurgeTexture(s->base); s->base = NULL;
3109         R_PurgeTexture(s->pants); s->pants = NULL;
3110         R_PurgeTexture(s->shirt); s->shirt = NULL;
3111         R_PurgeTexture(s->nmap); s->nmap = NULL;
3112         R_PurgeTexture(s->gloss); s->gloss = NULL;
3113         R_PurgeTexture(s->glow); s->glow = NULL;
3114         R_PurgeTexture(s->fog); s->fog = NULL;
3115         R_PurgeTexture(s->reflect); s->reflect = NULL;
3116         s->loadsequence = 0;
3117 }
3118
3119 void R_SkinFrame_Purge(void)
3120 {
3121         int i;
3122         skinframe_t *s;
3123         for (i = 0;i < SKINFRAME_HASH;i++)
3124         {
3125                 for (s = r_skinframe.hash[i];s;s = s->next)
3126                 {
3127                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3128                                 R_SkinFrame_PurgeSkinFrame(s);
3129                 }
3130         }
3131 }
3132
3133 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3134         skinframe_t *item;
3135         char basename[MAX_QPATH];
3136
3137         Image_StripImageExtension(name, basename, sizeof(basename));
3138
3139         if( last == NULL ) {
3140                 int hashindex;
3141                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3142                 item = r_skinframe.hash[hashindex];
3143         } else {
3144                 item = last->next;
3145         }
3146
3147         // linearly search through the hash bucket
3148         for( ; item ; item = item->next ) {
3149                 if( !strcmp( item->basename, basename ) ) {
3150                         return item;
3151                 }
3152         }
3153         return NULL;
3154 }
3155
3156 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3157 {
3158         skinframe_t *item;
3159         int hashindex;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3165         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3166                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3167                         break;
3168
3169         if (!item)
3170         {
3171                 if (!add)
3172                         return NULL;
3173                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3174                 memset(item, 0, sizeof(*item));
3175                 strlcpy(item->basename, basename, sizeof(item->basename));
3176                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3177                 item->comparewidth = comparewidth;
3178                 item->compareheight = compareheight;
3179                 item->comparecrc = comparecrc;
3180                 item->next = r_skinframe.hash[hashindex];
3181                 r_skinframe.hash[hashindex] = item;
3182         }
3183         else if (textureflags & TEXF_FORCE_RELOAD)
3184         {
3185                 if (!add)
3186                         return NULL;
3187                 R_SkinFrame_PurgeSkinFrame(item);
3188         }
3189
3190         R_SkinFrame_MarkUsed(item);
3191         return item;
3192 }
3193
3194 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3195         { \
3196                 unsigned long long avgcolor[5], wsum; \
3197                 int pix, comp, w; \
3198                 avgcolor[0] = 0; \
3199                 avgcolor[1] = 0; \
3200                 avgcolor[2] = 0; \
3201                 avgcolor[3] = 0; \
3202                 avgcolor[4] = 0; \
3203                 wsum = 0; \
3204                 for(pix = 0; pix < cnt; ++pix) \
3205                 { \
3206                         w = 0; \
3207                         for(comp = 0; comp < 3; ++comp) \
3208                                 w += getpixel; \
3209                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3210                         { \
3211                                 ++wsum; \
3212                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3213                                 w = getpixel; \
3214                                 for(comp = 0; comp < 3; ++comp) \
3215                                         avgcolor[comp] += getpixel * w; \
3216                                 avgcolor[3] += w; \
3217                         } \
3218                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3219                         avgcolor[4] += getpixel; \
3220                 } \
3221                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3222                         avgcolor[3] = 1; \
3223                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3224                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3225                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3226                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3227         }
3228
3229 extern cvar_t gl_picmip;
3230 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3231 {
3232         int j;
3233         unsigned char *pixels;
3234         unsigned char *bumppixels;
3235         unsigned char *basepixels = NULL;
3236         int basepixels_width = 0;
3237         int basepixels_height = 0;
3238         skinframe_t *skinframe;
3239         rtexture_t *ddsbase = NULL;
3240         qboolean ddshasalpha = false;
3241         float ddsavgcolor[4];
3242         char basename[MAX_QPATH];
3243         int miplevel = R_PicmipForFlags(textureflags);
3244         int savemiplevel = miplevel;
3245         int mymiplevel;
3246         char vabuf[1024];
3247
3248         if (cls.state == ca_dedicated)
3249                 return NULL;
3250
3251         // return an existing skinframe if already loaded
3252         // if loading of the first image fails, don't make a new skinframe as it
3253         // would cause all future lookups of this to be missing
3254         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3255         if (skinframe && skinframe->base)
3256                 return skinframe;
3257
3258         Image_StripImageExtension(name, basename, sizeof(basename));
3259
3260         // check for DDS texture file first
3261         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3262         {
3263                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3264                 if (basepixels == NULL && fallbacknotexture)
3265                         basepixels = Image_GenerateNoTexture();
3266                 if (basepixels == NULL)
3267                         return NULL;
3268         }
3269
3270         // FIXME handle miplevel
3271
3272         if (developer_loading.integer)
3273                 Con_Printf("loading skin \"%s\"\n", name);
3274
3275         // we've got some pixels to store, so really allocate this new texture now
3276         if (!skinframe)
3277                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3278         textureflags &= ~TEXF_FORCE_RELOAD;
3279         skinframe->stain = NULL;
3280         skinframe->merged = NULL;
3281         skinframe->base = NULL;
3282         skinframe->pants = NULL;
3283         skinframe->shirt = NULL;
3284         skinframe->nmap = NULL;
3285         skinframe->gloss = NULL;
3286         skinframe->glow = NULL;
3287         skinframe->fog = NULL;
3288         skinframe->reflect = NULL;
3289         skinframe->hasalpha = false;
3290         // we could store the q2animname here too
3291
3292         if (ddsbase)
3293         {
3294                 skinframe->base = ddsbase;
3295                 skinframe->hasalpha = ddshasalpha;
3296                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3297                 if (r_loadfog && skinframe->hasalpha)
3298                         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);
3299                 //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]);
3300         }
3301         else
3302         {
3303                 basepixels_width = image_width;
3304                 basepixels_height = image_height;
3305                 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);
3306                 if (textureflags & TEXF_ALPHA)
3307                 {
3308                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3309                         {
3310                                 if (basepixels[j] < 255)
3311                                 {
3312                                         skinframe->hasalpha = true;
3313                                         break;
3314                                 }
3315                         }
3316                         if (r_loadfog && skinframe->hasalpha)
3317                         {
3318                                 // has transparent pixels
3319                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3320                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3321                                 {
3322                                         pixels[j+0] = 255;
3323                                         pixels[j+1] = 255;
3324                                         pixels[j+2] = 255;
3325                                         pixels[j+3] = basepixels[j+3];
3326                                 }
3327                                 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);
3328                                 Mem_Free(pixels);
3329                         }
3330                 }
3331                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3332 #ifndef USE_GLES2
3333                 //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]);
3334                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3335                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3337                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3338 #endif
3339         }
3340
3341         if (r_loaddds)
3342         {
3343                 mymiplevel = savemiplevel;
3344                 if (r_loadnormalmap)
3345                         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);
3346                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3347                 if (r_loadgloss)
3348                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3349                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3350                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3351                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3352         }
3353
3354         // _norm is the name used by tenebrae and has been adopted as standard
3355         if (r_loadnormalmap && skinframe->nmap == NULL)
3356         {
3357                 mymiplevel = savemiplevel;
3358                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3359                 {
3360                         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);
3361                         Mem_Free(pixels);
3362                         pixels = NULL;
3363                 }
3364                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3365                 {
3366                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3368                         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);
3369                         Mem_Free(pixels);
3370                         Mem_Free(bumppixels);
3371                 }
3372                 else if (r_shadow_bumpscale_basetexture.value > 0)
3373                 {
3374                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3375                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3376                         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);
3377                         Mem_Free(pixels);
3378                 }
3379 #ifndef USE_GLES2
3380                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3381                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3382 #endif
3383         }
3384
3385         // _luma is supported only for tenebrae compatibility
3386         // _glow is the preferred name
3387         mymiplevel = savemiplevel;
3388         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))))
3389         {
3390                 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);
3391 #ifndef USE_GLES2
3392                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3393                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3394 #endif
3395                 Mem_Free(pixels);pixels = NULL;
3396         }
3397
3398         mymiplevel = savemiplevel;
3399         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3400         {
3401                 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);
3402 #ifndef USE_GLES2
3403                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3404                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3405 #endif
3406                 Mem_Free(pixels);
3407                 pixels = NULL;
3408         }
3409
3410         mymiplevel = savemiplevel;
3411         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3412         {
3413                 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);
3414 #ifndef USE_GLES2
3415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3416                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3417 #endif
3418                 Mem_Free(pixels);
3419                 pixels = NULL;
3420         }
3421
3422         mymiplevel = savemiplevel;
3423         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3424         {
3425                 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);
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3428                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3429 #endif
3430                 Mem_Free(pixels);
3431                 pixels = NULL;
3432         }
3433
3434         mymiplevel = savemiplevel;
3435         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3436         {
3437                 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);
3438 #ifndef USE_GLES2
3439                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3440                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3441 #endif
3442                 Mem_Free(pixels);
3443                 pixels = NULL;
3444         }
3445
3446         if (basepixels)
3447                 Mem_Free(basepixels);
3448
3449         return skinframe;
3450 }
3451
3452 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3453 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3454 {
3455         int i;
3456         skinframe_t *skinframe;
3457         char vabuf[1024];
3458
3459         if (cls.state == ca_dedicated)
3460                 return NULL;
3461
3462         // if already loaded just return it, otherwise make a new skinframe
3463         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3464         if (skinframe->base)
3465                 return skinframe;
3466         textureflags &= ~TEXF_FORCE_RELOAD;
3467
3468         skinframe->stain = NULL;
3469         skinframe->merged = NULL;
3470         skinframe->base = NULL;
3471         skinframe->pants = NULL;
3472         skinframe->shirt = NULL;
3473         skinframe->nmap = NULL;
3474         skinframe->gloss = NULL;
3475         skinframe->glow = NULL;
3476         skinframe->fog = NULL;
3477         skinframe->reflect = NULL;
3478         skinframe->hasalpha = false;
3479
3480         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3481         if (!skindata)
3482                 return NULL;
3483
3484         if (developer_loading.integer)
3485                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3486
3487         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3488         {
3489                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3490                 unsigned char *b = a + width * height * 4;
3491                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3492                 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);
3493                 Mem_Free(a);
3494         }
3495         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3496         if (textureflags & TEXF_ALPHA)
3497         {
3498                 for (i = 3;i < width * height * 4;i += 4)
3499                 {
3500                         if (skindata[i] < 255)
3501                         {
3502                                 skinframe->hasalpha = true;
3503                                 break;
3504                         }
3505                 }
3506                 if (r_loadfog && skinframe->hasalpha)
3507                 {
3508                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3509                         memcpy(fogpixels, skindata, width * height * 4);
3510                         for (i = 0;i < width * height * 4;i += 4)
3511                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3512                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3513                         Mem_Free(fogpixels);
3514                 }
3515         }
3516
3517         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3518         //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]);
3519
3520         return skinframe;
3521 }
3522
3523 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3524 {
3525         int i;
3526         int featuresmask;
3527         skinframe_t *skinframe;
3528
3529         if (cls.state == ca_dedicated)
3530                 return NULL;
3531
3532         // if already loaded just return it, otherwise make a new skinframe
3533         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3534         if (skinframe->base)
3535                 return skinframe;
3536         //textureflags &= ~TEXF_FORCE_RELOAD;
3537
3538         skinframe->stain = NULL;
3539         skinframe->merged = NULL;
3540         skinframe->base = NULL;
3541         skinframe->pants = NULL;
3542         skinframe->shirt = NULL;
3543         skinframe->nmap = NULL;
3544         skinframe->gloss = NULL;
3545         skinframe->glow = NULL;
3546         skinframe->fog = NULL;
3547         skinframe->reflect = NULL;
3548         skinframe->hasalpha = false;
3549
3550         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3551         if (!skindata)
3552                 return NULL;
3553
3554         if (developer_loading.integer)
3555                 Con_Printf("loading quake skin \"%s\"\n", name);
3556
3557         // 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)
3558         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3559         memcpy(skinframe->qpixels, skindata, width*height);
3560         skinframe->qwidth = width;
3561         skinframe->qheight = height;
3562
3563         featuresmask = 0;
3564         for (i = 0;i < width * height;i++)
3565                 featuresmask |= palette_featureflags[skindata[i]];
3566
3567         skinframe->hasalpha = false;
3568         // fence textures
3569         if (name[0] == '{')
3570                 skinframe->hasalpha = true;
3571         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3572         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3573         skinframe->qgeneratemerged = true;
3574         skinframe->qgeneratebase = skinframe->qhascolormapping;
3575         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3576
3577         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3578         //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]);
3579
3580         return skinframe;
3581 }
3582
3583 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3584 {
3585         int width;
3586         int height;
3587         unsigned char *skindata;
3588         char vabuf[1024];
3589
3590         if (!skinframe->qpixels)
3591                 return;
3592
3593         if (!skinframe->qhascolormapping)
3594                 colormapped = false;
3595
3596         if (colormapped)
3597         {
3598                 if (!skinframe->qgeneratebase)
3599                         return;
3600         }
3601         else
3602         {
3603                 if (!skinframe->qgeneratemerged)
3604                         return;
3605         }
3606
3607         width = skinframe->qwidth;
3608         height = skinframe->qheight;
3609         skindata = skinframe->qpixels;
3610
3611         if (skinframe->qgeneratenmap)
3612         {
3613                 unsigned char *a, *b;
3614                 skinframe->qgeneratenmap = false;
3615                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3616                 b = a + width * height * 4;
3617                 // use either a custom palette or the quake palette
3618                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3619                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3620                 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);
3621                 Mem_Free(a);
3622         }
3623
3624         if (skinframe->qgenerateglow)
3625         {
3626                 skinframe->qgenerateglow = false;
3627                 if (skinframe->hasalpha) // fence textures
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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3629                 else
3630                         skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3631         }
3632
3633         if (colormapped)
3634         {
3635                 skinframe->qgeneratebase = false;
3636                 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);
3637                 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);
3638                 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);
3639         }
3640         else
3641         {
3642                 skinframe->qgeneratemerged = false;
3643                 if (skinframe->hasalpha) // fence textures
3644                         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);
3645                 else
3646                         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);
3647         }
3648
3649         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3650         {
3651                 Mem_Free(skinframe->qpixels);
3652                 skinframe->qpixels = NULL;
3653         }
3654 }
3655
3656 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)
3657 {
3658         int i;
3659         skinframe_t *skinframe;
3660         char vabuf[1024];
3661
3662         if (cls.state == ca_dedicated)
3663                 return NULL;
3664
3665         // if already loaded just return it, otherwise make a new skinframe
3666         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3667         if (skinframe->base)
3668                 return skinframe;
3669         textureflags &= ~TEXF_FORCE_RELOAD;
3670
3671         skinframe->stain = NULL;
3672         skinframe->merged = NULL;
3673         skinframe->base = NULL;
3674         skinframe->pants = NULL;
3675         skinframe->shirt = NULL;
3676         skinframe->nmap = NULL;
3677         skinframe->gloss = NULL;
3678         skinframe->glow = NULL;
3679         skinframe->fog = NULL;
3680         skinframe->reflect = NULL;
3681         skinframe->hasalpha = false;
3682
3683         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3684         if (!skindata)
3685                 return NULL;
3686
3687         if (developer_loading.integer)
3688                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3689
3690         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3691         if ((textureflags & TEXF_ALPHA) && alphapalette)
3692         {
3693                 for (i = 0;i < width * height;i++)
3694                 {
3695                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3696                         {
3697                                 skinframe->hasalpha = true;
3698                                 break;
3699                         }
3700                 }
3701                 if (r_loadfog && skinframe->hasalpha)
3702                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3703         }
3704
3705         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3706         //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]);
3707
3708         return skinframe;
3709 }
3710
3711 skinframe_t *R_SkinFrame_LoadMissing(void)
3712 {
3713         skinframe_t *skinframe;
3714
3715         if (cls.state == ca_dedicated)
3716                 return NULL;
3717
3718         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3719         skinframe->stain = NULL;
3720         skinframe->merged = NULL;
3721         skinframe->base = NULL;
3722         skinframe->pants = NULL;
3723         skinframe->shirt = NULL;
3724         skinframe->nmap = NULL;
3725         skinframe->gloss = NULL;
3726         skinframe->glow = NULL;
3727         skinframe->fog = NULL;
3728         skinframe->reflect = NULL;
3729         skinframe->hasalpha = false;
3730
3731         skinframe->avgcolor[0] = rand() / RAND_MAX;
3732         skinframe->avgcolor[1] = rand() / RAND_MAX;
3733         skinframe->avgcolor[2] = rand() / RAND_MAX;
3734         skinframe->avgcolor[3] = 1;
3735
3736         return skinframe;
3737 }
3738
3739 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3740 {
3741         int x, y;
3742         static unsigned char pix[16][16][4];
3743
3744         if (cls.state == ca_dedicated)
3745                 return NULL;
3746
3747         // this makes a light grey/dark grey checkerboard texture
3748         if (!pix[0][0][3])
3749         {
3750                 for (y = 0; y < 16; y++)
3751                 {
3752                         for (x = 0; x < 16; x++)
3753                         {
3754                                 if ((y < 8) ^ (x < 8))
3755                                 {
3756                                         pix[y][x][0] = 128;
3757                                         pix[y][x][1] = 128;
3758                                         pix[y][x][2] = 128;
3759                                         pix[y][x][3] = 255;
3760                                 }
3761                                 else
3762                                 {
3763                                         pix[y][x][0] = 64;
3764                                         pix[y][x][1] = 64;
3765                                         pix[y][x][2] = 64;
3766                                         pix[y][x][3] = 255;
3767                                 }
3768                         }
3769                 }
3770         }
3771
3772         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3773 }
3774
3775 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3776 {
3777         skinframe_t *skinframe;
3778         if (cls.state == ca_dedicated)
3779                 return NULL;
3780         // if already loaded just return it, otherwise make a new skinframe
3781         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3782         if (skinframe->base)
3783                 return skinframe;
3784         textureflags &= ~TEXF_FORCE_RELOAD;
3785         skinframe->stain = NULL;
3786         skinframe->merged = NULL;
3787         skinframe->base = NULL;
3788         skinframe->pants = NULL;
3789         skinframe->shirt = NULL;
3790         skinframe->nmap = NULL;
3791         skinframe->gloss = NULL;
3792         skinframe->glow = NULL;
3793         skinframe->fog = NULL;
3794         skinframe->reflect = NULL;
3795         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3796         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3797         if (!tex)
3798                 return NULL;
3799         if (developer_loading.integer)
3800                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3801         skinframe->base = skinframe->merged = tex;
3802         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3803         return skinframe;
3804 }
3805
3806 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3807 typedef struct suffixinfo_s
3808 {
3809         const char *suffix;
3810         qboolean flipx, flipy, flipdiagonal;
3811 }
3812 suffixinfo_t;
3813 static suffixinfo_t suffix[3][6] =
3814 {
3815         {
3816                 {"px",   false, false, false},
3817                 {"nx",   false, false, false},
3818                 {"py",   false, false, false},
3819                 {"ny",   false, false, false},
3820                 {"pz",   false, false, false},
3821                 {"nz",   false, false, false}
3822         },
3823         {
3824                 {"posx", false, false, false},
3825                 {"negx", false, false, false},
3826                 {"posy", false, false, false},
3827                 {"negy", false, false, false},
3828                 {"posz", false, false, false},
3829                 {"negz", false, false, false}
3830         },
3831         {
3832                 {"rt",    true, false,  true},
3833                 {"lf",   false,  true,  true},
3834                 {"ft",    true,  true, false},
3835                 {"bk",   false, false, false},
3836                 {"up",    true, false,  true},
3837                 {"dn",    true, false,  true}
3838         }
3839 };
3840
3841 static int componentorder[4] = {0, 1, 2, 3};
3842
3843 static rtexture_t *R_LoadCubemap(const char *basename)
3844 {
3845         int i, j, cubemapsize;
3846         unsigned char *cubemappixels, *image_buffer;
3847         rtexture_t *cubemaptexture;
3848         char name[256];
3849         // must start 0 so the first loadimagepixels has no requested width/height
3850         cubemapsize = 0;
3851         cubemappixels = NULL;
3852         cubemaptexture = NULL;
3853         // keep trying different suffix groups (posx, px, rt) until one loads
3854         for (j = 0;j < 3 && !cubemappixels;j++)
3855         {
3856                 // load the 6 images in the suffix group
3857                 for (i = 0;i < 6;i++)
3858                 {
3859                         // generate an image name based on the base and and suffix
3860                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3861                         // load it
3862                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3863                         {
3864                                 // an image loaded, make sure width and height are equal
3865                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3866                                 {
3867                                         // if this is the first image to load successfully, allocate the cubemap memory
3868                                         if (!cubemappixels && image_width >= 1)
3869                                         {
3870                                                 cubemapsize = image_width;
3871                                                 // note this clears to black, so unavailable sides are black
3872                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3873                                         }
3874                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3875                                         if (cubemappixels)
3876                                                 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);
3877                                 }
3878                                 else
3879                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3880                                 // free the image
3881                                 Mem_Free(image_buffer);
3882                         }
3883                 }
3884         }
3885         // if a cubemap loaded, upload it
3886         if (cubemappixels)
3887         {
3888                 if (developer_loading.integer)
3889                         Con_Printf("loading cubemap \"%s\"\n", basename);
3890
3891                 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);
3892                 Mem_Free(cubemappixels);
3893         }
3894         else
3895         {
3896                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3897                 if (developer_loading.integer)
3898                 {
3899                         Con_Printf("(tried tried images ");
3900                         for (j = 0;j < 3;j++)
3901                                 for (i = 0;i < 6;i++)
3902                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3903                         Con_Print(" and was unable to find any of them).\n");
3904                 }
3905         }
3906         return cubemaptexture;
3907 }
3908
3909 rtexture_t *R_GetCubemap(const char *basename)
3910 {
3911         int i;
3912         for (i = 0;i < r_texture_numcubemaps;i++)
3913                 if (r_texture_cubemaps[i] != NULL)
3914                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3915                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3916         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3917                 return r_texture_whitecube;
3918         r_texture_numcubemaps++;
3919         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3920         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3921         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3922         return r_texture_cubemaps[i]->texture;
3923 }
3924
3925 static void R_Main_FreeViewCache(void)
3926 {
3927         if (r_refdef.viewcache.entityvisible)
3928                 Mem_Free(r_refdef.viewcache.entityvisible);
3929         if (r_refdef.viewcache.world_pvsbits)
3930                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3931         if (r_refdef.viewcache.world_leafvisible)
3932                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3933         if (r_refdef.viewcache.world_surfacevisible)
3934                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3935         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3936 }
3937
3938 static void R_Main_ResizeViewCache(void)
3939 {
3940         int numentities = r_refdef.scene.numentities;
3941         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3942         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3943         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3944         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3945         if (r_refdef.viewcache.maxentities < numentities)
3946         {
3947                 r_refdef.viewcache.maxentities = numentities;
3948                 if (r_refdef.viewcache.entityvisible)
3949                         Mem_Free(r_refdef.viewcache.entityvisible);
3950                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3951         }
3952         if (r_refdef.viewcache.world_numclusters != numclusters)
3953         {
3954                 r_refdef.viewcache.world_numclusters = numclusters;
3955                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3956                 if (r_refdef.viewcache.world_pvsbits)
3957                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3958                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3959         }
3960         if (r_refdef.viewcache.world_numleafs != numleafs)
3961         {
3962                 r_refdef.viewcache.world_numleafs = numleafs;
3963                 if (r_refdef.viewcache.world_leafvisible)
3964                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3965                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3966         }
3967         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3968         {
3969                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3970                 if (r_refdef.viewcache.world_surfacevisible)
3971                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3972                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3973         }
3974 }
3975
3976 extern rtexture_t *loadingscreentexture;
3977 static void gl_main_start(void)
3978 {
3979         loadingscreentexture = NULL;
3980         r_texture_blanknormalmap = NULL;
3981         r_texture_white = NULL;
3982         r_texture_grey128 = NULL;
3983         r_texture_black = NULL;
3984         r_texture_whitecube = NULL;
3985         r_texture_normalizationcube = NULL;
3986         r_texture_fogattenuation = NULL;
3987         r_texture_fogheighttexture = NULL;
3988         r_texture_gammaramps = NULL;
3989         r_texture_numcubemaps = 0;
3990         r_uniformbufferalignment = 32;
3991
3992         r_loaddds = r_texture_dds_load.integer != 0;
3993         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3994
3995         switch(vid.renderpath)
3996         {
3997         case RENDERPATH_GL20:
3998         case RENDERPATH_D3D9:
3999         case RENDERPATH_D3D10:
4000         case RENDERPATH_D3D11:
4001         case RENDERPATH_SOFT:
4002         case RENDERPATH_GLES2:
4003                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4004                 Cvar_SetValueQuick(&gl_combine, 1);
4005                 Cvar_SetValueQuick(&r_glsl, 1);
4006                 r_loadnormalmap = true;
4007                 r_loadgloss = true;
4008                 r_loadfog = false;
4009 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4010                 if (vid.support.arb_uniform_buffer_object)
4011                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012 #endif
4013                         break;
4014         case RENDERPATH_GL13:
4015         case RENDERPATH_GLES1:
4016                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017                 Cvar_SetValueQuick(&gl_combine, 1);
4018                 Cvar_SetValueQuick(&r_glsl, 0);
4019                 r_loadnormalmap = false;
4020                 r_loadgloss = false;
4021                 r_loadfog = true;
4022                 break;
4023         case RENDERPATH_GL11:
4024                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025                 Cvar_SetValueQuick(&gl_combine, 0);
4026                 Cvar_SetValueQuick(&r_glsl, 0);
4027                 r_loadnormalmap = false;
4028                 r_loadgloss = false;
4029                 r_loadfog = true;
4030                 break;
4031         }
4032
4033         R_AnimCache_Free();
4034         R_FrameData_Reset();
4035         R_BufferData_Reset();
4036
4037         r_numqueries = 0;
4038         r_maxqueries = 0;
4039         memset(r_queries, 0, sizeof(r_queries));
4040
4041         r_qwskincache = NULL;
4042         r_qwskincache_size = 0;
4043
4044         // due to caching of texture_t references, the collision cache must be reset
4045         Collision_Cache_Reset(true);
4046
4047         // set up r_skinframe loading system for textures
4048         memset(&r_skinframe, 0, sizeof(r_skinframe));
4049         r_skinframe.loadsequence = 1;
4050         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4051
4052         r_main_texturepool = R_AllocTexturePool();
4053         R_BuildBlankTextures();
4054         R_BuildNoTexture();
4055         if (vid.support.arb_texture_cube_map)
4056         {
4057                 R_BuildWhiteCube();
4058                 R_BuildNormalizationCube();
4059         }
4060         r_texture_fogattenuation = NULL;
4061         r_texture_fogheighttexture = NULL;
4062         r_texture_gammaramps = NULL;
4063         //r_texture_fogintensity = NULL;
4064         memset(&r_fb, 0, sizeof(r_fb));
4065         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4066         r_glsl_permutation = NULL;
4067         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4068         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4069 #ifdef SUPPORTD3D
4070         r_hlsl_permutation = NULL;
4071         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4072         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4073 #endif
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075
4076         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077         r_texture_numcubemaps = 0;
4078
4079         r_refdef.fogmasktable_density = 0;
4080
4081 #ifdef __ANDROID__
4082         // For Steelstorm Android
4083         // FIXME CACHE the program and reload
4084         // FIXME see possible combinations for SS:BR android
4085         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4086         R_SetupShader_SetPermutationGLSL(0, 12);
4087         R_SetupShader_SetPermutationGLSL(0, 13);
4088         R_SetupShader_SetPermutationGLSL(0, 8388621);
4089         R_SetupShader_SetPermutationGLSL(3, 0);
4090         R_SetupShader_SetPermutationGLSL(3, 2048);
4091         R_SetupShader_SetPermutationGLSL(5, 0);
4092         R_SetupShader_SetPermutationGLSL(5, 2);
4093         R_SetupShader_SetPermutationGLSL(5, 2048);
4094         R_SetupShader_SetPermutationGLSL(5, 8388608);
4095         R_SetupShader_SetPermutationGLSL(11, 1);
4096         R_SetupShader_SetPermutationGLSL(11, 2049);
4097         R_SetupShader_SetPermutationGLSL(11, 8193);
4098         R_SetupShader_SetPermutationGLSL(11, 10241);
4099         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4100 #endif
4101 }
4102
4103 static void gl_main_shutdown(void)
4104 {
4105         R_RenderTarget_FreeUnused(true);
4106         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4107         R_AnimCache_Free();
4108         R_FrameData_Reset();
4109         R_BufferData_Reset();
4110
4111         R_Main_FreeViewCache();
4112
4113         switch(vid.renderpath)
4114         {
4115         case RENDERPATH_GL11:
4116         case RENDERPATH_GL13:
4117         case RENDERPATH_GL20:
4118         case RENDERPATH_GLES1:
4119         case RENDERPATH_GLES2:
4120 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4121                 if (r_maxqueries)
4122                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4123 #endif
4124                 break;
4125         case RENDERPATH_D3D9:
4126                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4127                 break;
4128         case RENDERPATH_D3D10:
4129                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4130                 break;
4131         case RENDERPATH_D3D11:
4132                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4133                 break;
4134         case RENDERPATH_SOFT:
4135                 break;
4136         }
4137
4138         r_numqueries = 0;
4139         r_maxqueries = 0;
4140         memset(r_queries, 0, sizeof(r_queries));
4141
4142         r_qwskincache = NULL;
4143         r_qwskincache_size = 0;
4144
4145         // clear out the r_skinframe state
4146         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4147         memset(&r_skinframe, 0, sizeof(r_skinframe));
4148
4149         if (r_svbsp.nodes)
4150                 Mem_Free(r_svbsp.nodes);
4151         memset(&r_svbsp, 0, sizeof (r_svbsp));
4152         R_FreeTexturePool(&r_main_texturepool);
4153         loadingscreentexture = NULL;
4154         r_texture_blanknormalmap = NULL;
4155         r_texture_white = NULL;
4156         r_texture_grey128 = NULL;
4157         r_texture_black = NULL;
4158         r_texture_whitecube = NULL;
4159         r_texture_normalizationcube = NULL;
4160         r_texture_fogattenuation = NULL;
4161         r_texture_fogheighttexture = NULL;
4162         r_texture_gammaramps = NULL;
4163         r_texture_numcubemaps = 0;
4164         //r_texture_fogintensity = NULL;
4165         memset(&r_fb, 0, sizeof(r_fb));
4166         R_GLSL_Restart_f();
4167
4168         r_glsl_permutation = NULL;
4169         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4170         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4171 #ifdef SUPPORTD3D
4172         r_hlsl_permutation = NULL;
4173         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4174         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4175 #endif
4176 }
4177
4178 static void gl_main_newmap(void)
4179 {
4180         // FIXME: move this code to client
4181         char *entities, entname[MAX_QPATH];
4182         if (r_qwskincache)
4183                 Mem_Free(r_qwskincache);
4184         r_qwskincache = NULL;
4185         r_qwskincache_size = 0;
4186         if (cl.worldmodel)
4187         {
4188                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4189                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4190                 {
4191                         CL_ParseEntityLump(entities);
4192                         Mem_Free(entities);
4193                         return;
4194                 }
4195                 if (cl.worldmodel->brush.entities)
4196                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4197         }
4198         R_Main_FreeViewCache();
4199
4200         R_FrameData_Reset();
4201         R_BufferData_Reset();
4202 }
4203
4204 void GL_Main_Init(void)
4205 {
4206         int i;
4207         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4208         R_InitShaderModeInfo();
4209
4210         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4211         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4212         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4213         if (gamemode == GAME_NEHAHRA)
4214         {
4215                 Cvar_RegisterVariable (&gl_fogenable);
4216                 Cvar_RegisterVariable (&gl_fogdensity);
4217                 Cvar_RegisterVariable (&gl_fogred);
4218                 Cvar_RegisterVariable (&gl_foggreen);
4219                 Cvar_RegisterVariable (&gl_fogblue);
4220                 Cvar_RegisterVariable (&gl_fogstart);
4221                 Cvar_RegisterVariable (&gl_fogend);
4222                 Cvar_RegisterVariable (&gl_skyclip);
4223         }
4224         Cvar_RegisterVariable(&r_motionblur);
4225         Cvar_RegisterVariable(&r_damageblur);
4226         Cvar_RegisterVariable(&r_motionblur_averaging);
4227         Cvar_RegisterVariable(&r_motionblur_randomize);
4228         Cvar_RegisterVariable(&r_motionblur_minblur);
4229         Cvar_RegisterVariable(&r_motionblur_maxblur);
4230         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4231         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4232         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4233         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4234         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4235         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4236         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4237         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4238         Cvar_RegisterVariable(&r_equalize_entities_by);
4239         Cvar_RegisterVariable(&r_equalize_entities_to);
4240         Cvar_RegisterVariable(&r_depthfirst);
4241         Cvar_RegisterVariable(&r_useinfinitefarclip);
4242         Cvar_RegisterVariable(&r_farclip_base);
4243         Cvar_RegisterVariable(&r_farclip_world);
4244         Cvar_RegisterVariable(&r_nearclip);
4245         Cvar_RegisterVariable(&r_deformvertexes);
4246         Cvar_RegisterVariable(&r_transparent);
4247         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4248         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4249         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4250         Cvar_RegisterVariable(&r_showoverdraw);
4251         Cvar_RegisterVariable(&r_showbboxes);
4252         Cvar_RegisterVariable(&r_showbboxes_client);
4253         Cvar_RegisterVariable(&r_showsurfaces);
4254         Cvar_RegisterVariable(&r_showtris);
4255         Cvar_RegisterVariable(&r_shownormals);
4256         Cvar_RegisterVariable(&r_showlighting);
4257         Cvar_RegisterVariable(&r_showshadowvolumes);
4258         Cvar_RegisterVariable(&r_showcollisionbrushes);
4259         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4260         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4261         Cvar_RegisterVariable(&r_showdisabledepthtest);
4262         Cvar_RegisterVariable(&r_drawportals);
4263         Cvar_RegisterVariable(&r_drawentities);
4264         Cvar_RegisterVariable(&r_draw2d);
4265         Cvar_RegisterVariable(&r_drawworld);
4266         Cvar_RegisterVariable(&r_cullentities_trace);
4267         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4268         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4269         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4270         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4271         Cvar_RegisterVariable(&r_cullentities_trace_expand);
4272         Cvar_RegisterVariable(&r_cullentities_trace_pad);
4273         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4274         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4275         Cvar_RegisterVariable(&r_sortentities);
4276         Cvar_RegisterVariable(&r_drawviewmodel);
4277         Cvar_RegisterVariable(&r_drawexteriormodel);
4278         Cvar_RegisterVariable(&r_speeds);
4279         Cvar_RegisterVariable(&r_fullbrights);
4280         Cvar_RegisterVariable(&r_wateralpha);
4281         Cvar_RegisterVariable(&r_dynamic);
4282         Cvar_RegisterVariable(&r_fakelight);
4283         Cvar_RegisterVariable(&r_fakelight_intensity);
4284         Cvar_RegisterVariable(&r_fullbright_directed);
4285         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4286         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4287         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4288         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4289         Cvar_RegisterVariable(&r_fullbright);
4290         Cvar_RegisterVariable(&r_shadows);
4291         Cvar_RegisterVariable(&r_shadows_darken);
4292         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4293         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4294         Cvar_RegisterVariable(&r_shadows_throwdistance);
4295         Cvar_RegisterVariable(&r_shadows_throwdirection);
4296         Cvar_RegisterVariable(&r_shadows_focus);
4297         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4298         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4299         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4300         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4301         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4302         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4303         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4304         Cvar_RegisterVariable(&r_fog_exp2);
4305         Cvar_RegisterVariable(&r_fog_clear);
4306         Cvar_RegisterVariable(&r_drawfog);
4307         Cvar_RegisterVariable(&r_transparentdepthmasking);
4308         Cvar_RegisterVariable(&r_transparent_sortmindist);
4309         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4310         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4311         Cvar_RegisterVariable(&r_texture_dds_load);
4312         Cvar_RegisterVariable(&r_texture_dds_save);
4313         Cvar_RegisterVariable(&r_textureunits);
4314         Cvar_RegisterVariable(&gl_combine);
4315         Cvar_RegisterVariable(&r_usedepthtextures);
4316         Cvar_RegisterVariable(&r_viewfbo);
4317         Cvar_RegisterVariable(&r_rendertarget_debug);
4318         Cvar_RegisterVariable(&r_viewscale);
4319         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4320         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4321         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4322         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4323         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4324         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4325         Cvar_RegisterVariable(&r_glsl);
4326         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4327         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4328         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4329         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4330         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4331         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4332         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4333         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4334         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4335         Cvar_RegisterVariable(&r_glsl_postprocess);
4336         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4337         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4338         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4339         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4340         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4341         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4342         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4343         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4344         Cvar_RegisterVariable(&r_celshading);
4345         Cvar_RegisterVariable(&r_celoutlines);
4346
4347         Cvar_RegisterVariable(&r_water);
4348         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4349         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4350         Cvar_RegisterVariable(&r_water_clippingplanebias);
4351         Cvar_RegisterVariable(&r_water_refractdistort);
4352         Cvar_RegisterVariable(&r_water_reflectdistort);
4353         Cvar_RegisterVariable(&r_water_scissormode);
4354         Cvar_RegisterVariable(&r_water_lowquality);
4355         Cvar_RegisterVariable(&r_water_hideplayer);
4356
4357         Cvar_RegisterVariable(&r_lerpsprites);
4358         Cvar_RegisterVariable(&r_lerpmodels);
4359         Cvar_RegisterVariable(&r_lerplightstyles);
4360         Cvar_RegisterVariable(&r_waterscroll);
4361         Cvar_RegisterVariable(&r_bloom);
4362         Cvar_RegisterVariable(&r_bloom_colorscale);
4363         Cvar_RegisterVariable(&r_bloom_brighten);
4364         Cvar_RegisterVariable(&r_bloom_blur);
4365         Cvar_RegisterVariable(&r_bloom_resolution);
4366         Cvar_RegisterVariable(&r_bloom_colorexponent);
4367         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4368         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4369         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4370         Cvar_RegisterVariable(&r_hdr_glowintensity);
4371         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4372         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4373         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4374         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4375         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4376         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4377         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4378         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4379         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4380         Cvar_RegisterVariable(&developer_texturelogging);
4381         Cvar_RegisterVariable(&gl_lightmaps);
4382         Cvar_RegisterVariable(&r_test);
4383         Cvar_RegisterVariable(&r_batch_multidraw);
4384         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4385         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4386         Cvar_RegisterVariable(&r_glsl_skeletal);
4387         Cvar_RegisterVariable(&r_glsl_saturation);
4388         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4389         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4390         Cvar_RegisterVariable(&r_framedatasize);
4391         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4392                 Cvar_RegisterVariable(&r_buffermegs[i]);
4393         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4394         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4395                 Cvar_SetValue("r_fullbrights", 0);
4396 #ifdef DP_MOBILETOUCH
4397         // GLES devices have terrible depth precision in general, so...
4398         Cvar_SetValueQuick(&r_nearclip, 4);
4399         Cvar_SetValueQuick(&r_farclip_base, 4096);
4400         Cvar_SetValueQuick(&r_farclip_world, 0);
4401         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4402 #endif
4403         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4404 }
4405
4406 void Render_Init(void)
4407 {
4408         gl_backend_init();
4409         R_Textures_Init();
4410         GL_Main_Init();
4411         Font_Init();
4412         GL_Draw_Init();
4413         R_Shadow_Init();
4414         R_Sky_Init();
4415         GL_Surf_Init();
4416         Sbar_Init();
4417         R_Particles_Init();
4418         R_Explosion_Init();
4419         R_LightningBeams_Init();
4420         Mod_RenderInit();
4421 }
4422
4423 /*
4424 ===============
4425 GL_Init
4426 ===============
4427 */
4428 #ifndef USE_GLES2
4429 extern char *ENGINE_EXTENSIONS;
4430 void GL_Init (void)
4431 {
4432         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4433         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4434         gl_version = (const char *)qglGetString(GL_VERSION);
4435         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4436
4437         if (!gl_extensions)
4438                 gl_extensions = "";
4439         if (!gl_platformextensions)
4440                 gl_platformextensions = "";
4441
4442         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4443         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4444         Con_Printf("GL_VERSION: %s\n", gl_version);
4445         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4446         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4447
4448         VID_CheckExtensions();
4449
4450         // LordHavoc: report supported extensions
4451 #ifdef CONFIG_MENU
4452         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4453 #else
4454         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4455 #endif
4456
4457         // clear to black (loading plaque will be seen over this)
4458         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4459 }
4460 #endif
4461
4462 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4463 {
4464         int i;
4465         mplane_t *p;
4466         if (r_trippy.integer)
4467                 return false;
4468         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4469         {
4470                 p = r_refdef.view.frustum + i;
4471                 switch(p->signbits)
4472                 {
4473                 default:
4474                 case 0:
4475                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 1:
4479                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 2:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 3:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 4:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 5:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 6:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 7:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 }
4507         }
4508         return false;
4509 }
4510
4511 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4512 {
4513         int i;
4514         const mplane_t *p;
4515         if (r_trippy.integer)
4516                 return false;
4517         for (i = 0;i < numplanes;i++)
4518         {
4519                 p = planes + i;
4520                 switch(p->signbits)
4521                 {
4522                 default:
4523                 case 0:
4524                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 1:
4528                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 case 2:
4532                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4533                                 return true;
4534                         break;
4535                 case 3:
4536                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4537                                 return true;
4538                         break;
4539                 case 4:
4540                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4541                                 return true;
4542                         break;
4543                 case 5:
4544                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4545                                 return true;
4546                         break;
4547                 case 6:
4548                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4549                                 return true;
4550                         break;
4551                 case 7:
4552                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4553                                 return true;
4554                         break;
4555                 }
4556         }
4557         return false;
4558 }
4559
4560 //==================================================================================
4561
4562 // LordHavoc: this stores temporary data used within the same frame
4563
4564 typedef struct r_framedata_mem_s
4565 {
4566         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4567         size_t size; // how much usable space
4568         size_t current; // how much space in use
4569         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4570         size_t wantedsize; // how much space was allocated
4571         unsigned char *data; // start of real data (16byte aligned)
4572 }
4573 r_framedata_mem_t;
4574
4575 static r_framedata_mem_t *r_framedata_mem;
4576
4577 void R_FrameData_Reset(void)
4578 {
4579         while (r_framedata_mem)
4580         {
4581                 r_framedata_mem_t *next = r_framedata_mem->purge;
4582                 Mem_Free(r_framedata_mem);
4583                 r_framedata_mem = next;
4584         }
4585 }
4586
4587 static void R_FrameData_Resize(qboolean mustgrow)
4588 {
4589         size_t wantedsize;
4590         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4591         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4592         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4593         {
4594                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4595                 newmem->wantedsize = wantedsize;
4596                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4597                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4598                 newmem->current = 0;
4599                 newmem->mark = 0;
4600                 newmem->purge = r_framedata_mem;
4601                 r_framedata_mem = newmem;
4602         }
4603 }
4604
4605 void R_FrameData_NewFrame(void)
4606 {
4607         R_FrameData_Resize(false);
4608         if (!r_framedata_mem)
4609                 return;
4610         // if we ran out of space on the last frame, free the old memory now
4611         while (r_framedata_mem->purge)
4612         {
4613                 // repeatedly remove the second item in the list, leaving only head
4614                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4615                 Mem_Free(r_framedata_mem->purge);
4616                 r_framedata_mem->purge = next;
4617         }
4618         // reset the current mem pointer
4619         r_framedata_mem->current = 0;
4620         r_framedata_mem->mark = 0;
4621 }
4622
4623 void *R_FrameData_Alloc(size_t size)
4624 {
4625         void *data;
4626         float newvalue;
4627
4628         // align to 16 byte boundary - the data pointer is already aligned, so we
4629         // only need to ensure the size of every allocation is also aligned
4630         size = (size + 15) & ~15;
4631
4632         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4633         {
4634                 // emergency - we ran out of space, allocate more memory
4635                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4636                 newvalue = r_framedatasize.value * 2.0f;
4637                 // 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
4638                 if (sizeof(size_t) >= 8)
4639                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4640                 else
4641                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4642                 // this might not be a growing it, but we'll allocate another buffer every time
4643                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4644                 R_FrameData_Resize(true);
4645         }
4646
4647         data = r_framedata_mem->data + r_framedata_mem->current;
4648         r_framedata_mem->current += size;
4649
4650         // count the usage for stats
4651         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4652         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4653
4654         return (void *)data;
4655 }
4656
4657 void *R_FrameData_Store(size_t size, void *data)
4658 {
4659         void *d = R_FrameData_Alloc(size);
4660         if (d && data)
4661                 memcpy(d, data, size);
4662         return d;
4663 }
4664
4665 void R_FrameData_SetMark(void)
4666 {
4667         if (!r_framedata_mem)
4668                 return;
4669         r_framedata_mem->mark = r_framedata_mem->current;
4670 }
4671
4672 void R_FrameData_ReturnToMark(void)
4673 {
4674         if (!r_framedata_mem)
4675                 return;
4676         r_framedata_mem->current = r_framedata_mem->mark;
4677 }
4678
4679 //==================================================================================
4680
4681 // avoid reusing the same buffer objects on consecutive frames
4682 #define R_BUFFERDATA_CYCLE 3
4683
4684 typedef struct r_bufferdata_buffer_s
4685 {
4686         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4687         size_t size; // how much usable space
4688         size_t current; // how much space in use
4689         r_meshbuffer_t *buffer; // the buffer itself
4690 }
4691 r_bufferdata_buffer_t;
4692
4693 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4694 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4695
4696 /// frees all dynamic buffers
4697 void R_BufferData_Reset(void)
4698 {
4699         int cycle, type;
4700         r_bufferdata_buffer_t **p, *mem;
4701         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4702         {
4703                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4704                 {
4705                         // free all buffers
4706                         p = &r_bufferdata_buffer[cycle][type];
4707                         while (*p)
4708                         {
4709                                 mem = *p;
4710                                 *p = (*p)->purge;
4711                                 if (mem->buffer)
4712                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4713                                 Mem_Free(mem);
4714                         }
4715                 }
4716         }
4717 }
4718
4719 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4720 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4721 {
4722         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4723         size_t size;
4724         float newvalue = r_buffermegs[type].value;
4725
4726         // increase the cvar if we have to (but only if we already have a mem)
4727         if (mustgrow && mem)
4728                 newvalue *= 2.0f;
4729         newvalue = bound(0.25f, newvalue, 256.0f);
4730         while (newvalue * 1024*1024 < minsize)
4731                 newvalue *= 2.0f;
4732
4733         // clamp the cvar to valid range
4734         newvalue = bound(0.25f, newvalue, 256.0f);
4735         if (r_buffermegs[type].value != newvalue)
4736                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4737
4738         // calculate size in bytes
4739         size = (size_t)(newvalue * 1024*1024);
4740         size = bound(131072, size, 256*1024*1024);
4741
4742         // allocate a new buffer if the size is different (purge old one later)
4743         // or if we were told we must grow the buffer
4744         if (!mem || mem->size != size || mustgrow)
4745         {
4746                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4747                 mem->size = size;
4748                 mem->current = 0;
4749                 if (type == R_BUFFERDATA_VERTEX)
4750                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4751                 else if (type == R_BUFFERDATA_INDEX16)
4752                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4753                 else if (type == R_BUFFERDATA_INDEX32)
4754                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4755                 else if (type == R_BUFFERDATA_UNIFORM)
4756                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4757                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4758                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4759         }
4760 }
4761
4762 void R_BufferData_NewFrame(void)
4763 {
4764         int type;
4765         r_bufferdata_buffer_t **p, *mem;
4766         // cycle to the next frame's buffers
4767         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4768         // if we ran out of space on the last time we used these buffers, free the old memory now
4769         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4770         {
4771                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4772                 {
4773                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4774                         // free all but the head buffer, this is how we recycle obsolete
4775                         // buffers after they are no longer in use
4776                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4777                         while (*p)
4778                         {
4779                                 mem = *p;
4780                                 *p = (*p)->purge;
4781                                 if (mem->buffer)
4782                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4783                                 Mem_Free(mem);
4784                         }
4785                         // reset the current offset
4786                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4787                 }
4788         }
4789 }
4790
4791 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4792 {
4793         r_bufferdata_buffer_t *mem;
4794         int offset = 0;
4795         int padsize;
4796
4797         *returnbufferoffset = 0;
4798
4799         // align size to a byte boundary appropriate for the buffer type, this
4800         // makes all allocations have aligned start offsets
4801         if (type == R_BUFFERDATA_UNIFORM)
4802                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4803         else
4804                 padsize = (datasize + 15) & ~15;
4805
4806         // if we ran out of space in this buffer we must allocate a new one
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                 R_BufferData_Resize(type, true, padsize);
4809
4810         // if the resize did not give us enough memory, fail
4811         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4812                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4813
4814         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4815         offset = (int)mem->current;
4816         mem->current += padsize;
4817
4818         // upload the data to the buffer at the chosen offset
4819         if (offset == 0)
4820                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4821         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4822
4823         // count the usage for stats
4824         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4825         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4826
4827         // return the buffer offset
4828         *returnbufferoffset = offset;
4829
4830         return mem->buffer;
4831 }
4832
4833 //==================================================================================
4834
4835 // LordHavoc: animcache originally written by Echon, rewritten since then
4836
4837 /**
4838  * Animation cache prevents re-generating mesh data for an animated model
4839  * multiple times in one frame for lighting, shadowing, reflections, etc.
4840  */
4841
4842 void R_AnimCache_Free(void)
4843 {
4844 }
4845
4846 void R_AnimCache_ClearCache(void)
4847 {
4848         int i;
4849         entity_render_t *ent;
4850
4851         for (i = 0;i < r_refdef.scene.numentities;i++)
4852         {
4853                 ent = r_refdef.scene.entities[i];
4854                 ent->animcache_vertex3f = NULL;
4855                 ent->animcache_vertex3f_vertexbuffer = NULL;
4856                 ent->animcache_vertex3f_bufferoffset = 0;
4857                 ent->animcache_normal3f = NULL;
4858                 ent->animcache_normal3f_vertexbuffer = NULL;
4859                 ent->animcache_normal3f_bufferoffset = 0;
4860                 ent->animcache_svector3f = NULL;
4861                 ent->animcache_svector3f_vertexbuffer = NULL;
4862                 ent->animcache_svector3f_bufferoffset = 0;
4863                 ent->animcache_tvector3f = NULL;
4864                 ent->animcache_tvector3f_vertexbuffer = NULL;
4865                 ent->animcache_tvector3f_bufferoffset = 0;
4866                 ent->animcache_vertexmesh = NULL;
4867                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4868                 ent->animcache_vertexmesh_bufferoffset = 0;
4869                 ent->animcache_skeletaltransform3x4 = NULL;
4870                 ent->animcache_skeletaltransform3x4buffer = NULL;
4871                 ent->animcache_skeletaltransform3x4offset = 0;
4872                 ent->animcache_skeletaltransform3x4size = 0;
4873         }
4874 }
4875
4876 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4877 {
4878         int i;
4879
4880         // check if we need the meshbuffers
4881         if (!vid.useinterleavedarrays)
4882                 return;
4883
4884         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4885                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4886         // TODO: upload vertexbuffer?
4887         if (ent->animcache_vertexmesh)
4888         {
4889                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4890                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4891                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4892                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4893                 for (i = 0;i < numvertices;i++)
4894                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4895                 if (ent->animcache_svector3f)
4896                         for (i = 0;i < numvertices;i++)
4897                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4898                 if (ent->animcache_tvector3f)
4899                         for (i = 0;i < numvertices;i++)
4900                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4901                 if (ent->animcache_normal3f)
4902                         for (i = 0;i < numvertices;i++)
4903                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4904         }
4905 }
4906
4907 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4908 {
4909         dp_model_t *model = ent->model;
4910         int numvertices;
4911
4912         // see if this ent is worth caching
4913         if (!model || !model->Draw || !model->AnimateVertices)
4914                 return false;
4915         // nothing to cache if it contains no animations and has no skeleton
4916         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4917                 return false;
4918         // see if it is already cached for gpuskeletal
4919         if (ent->animcache_skeletaltransform3x4)
4920                 return false;
4921         // see if it is already cached as a mesh
4922         if (ent->animcache_vertex3f)
4923         {
4924                 // check if we need to add normals or tangents
4925                 if (ent->animcache_normal3f)
4926                         wantnormals = false;
4927                 if (ent->animcache_svector3f)
4928                         wanttangents = false;
4929                 if (!wantnormals && !wanttangents)
4930                         return false;
4931         }
4932
4933         // check which kind of cache we need to generate
4934         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4935         {
4936                 // cache the skeleton so the vertex shader can use it
4937                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4938                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4939                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4940                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4941                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4942                 // note: this can fail if the buffer is at the grow limit
4943                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4944                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4945         }
4946         else if (ent->animcache_vertex3f)
4947         {
4948                 // mesh was already cached but we may need to add normals/tangents
4949                 // (this only happens with multiple views, reflections, cameras, etc)
4950                 if (wantnormals || wanttangents)
4951                 {
4952                         numvertices = model->surfmesh.num_vertices;
4953                         if (wantnormals)
4954                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4955                         if (wanttangents)
4956                         {
4957                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4958                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4959                         }
4960                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4961                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4962                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4963                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4964                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4965                 }
4966         }
4967         else
4968         {
4969                 // generate mesh cache
4970                 numvertices = model->surfmesh.num_vertices;
4971                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4972                 if (wantnormals)
4973                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4974                 if (wanttangents)
4975                 {
4976                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                 }
4979                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4980                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981                 if (wantnormals || wanttangents)
4982                 {
4983                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4984                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4985                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4986                 }
4987                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4988                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4989                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4990         }
4991         return true;
4992 }
4993
4994 void R_AnimCache_CacheVisibleEntities(void)
4995 {
4996         int i;
4997         qboolean wantnormals = true;
4998         qboolean wanttangents = !r_showsurfaces.integer;
4999
5000         switch(vid.renderpath)
5001         {
5002         case RENDERPATH_GL20:
5003         case RENDERPATH_D3D9:
5004         case RENDERPATH_D3D10:
5005         case RENDERPATH_D3D11:
5006         case RENDERPATH_GLES2:
5007                 break;
5008         case RENDERPATH_GL11:
5009         case RENDERPATH_GL13:
5010         case RENDERPATH_GLES1:
5011                 wanttangents = false;
5012                 break;
5013         case RENDERPATH_SOFT:
5014                 break;
5015         }
5016
5017         if (r_shownormals.integer)
5018                 wanttangents = wantnormals = true;
5019
5020         // TODO: thread this
5021         // NOTE: R_PrepareRTLights() also caches entities
5022
5023         for (i = 0;i < r_refdef.scene.numentities;i++)
5024                 if (r_refdef.viewcache.entityvisible[i])
5025                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5026 }
5027
5028 //==================================================================================
5029
5030 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5031 {
5032         int i;
5033         vec3_t eyemins, eyemaxs;
5034         vec3_t boxmins, boxmaxs;
5035         vec3_t padmins, padmaxs;
5036         vec3_t start;
5037         vec3_t end;
5038         dp_model_t *model = r_refdef.scene.worldmodel;
5039         static vec3_t positions[] = {
5040                 { 0.5f, 0.5f, 0.5f },
5041                 { 0.0f, 0.0f, 0.0f },
5042                 { 0.0f, 0.0f, 1.0f },
5043                 { 0.0f, 1.0f, 0.0f },
5044                 { 0.0f, 1.0f, 1.0f },
5045                 { 1.0f, 0.0f, 0.0f },
5046                 { 1.0f, 0.0f, 1.0f },
5047                 { 1.0f, 1.0f, 0.0f },
5048                 { 1.0f, 1.0f, 1.0f },
5049         };
5050
5051         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5052         if (numsamples < 0)
5053                 return true;
5054
5055         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5056         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5057                 return true;
5058
5059         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5060                 return true;
5061
5062         // expand the eye box a little
5063         eyemins[0] = eye[0] - eyejitter;
5064         eyemaxs[0] = eye[0] + eyejitter;
5065         eyemins[1] = eye[1] - eyejitter;
5066         eyemaxs[1] = eye[1] + eyejitter;
5067         eyemins[2] = eye[2] - eyejitter;
5068         eyemaxs[2] = eye[2] + eyejitter;
5069         // expand the box a little
5070         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
5071         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
5072         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
5073         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
5074         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
5075         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
5076         // make an even larger box for the acceptable area
5077         padmins[0] = boxmins[0] - pad;
5078         padmaxs[0] = boxmaxs[0] + pad;
5079         padmins[1] = boxmins[1] - pad;
5080         padmaxs[1] = boxmaxs[1] + pad;
5081         padmins[2] = boxmins[2] - pad;
5082         padmaxs[2] = boxmaxs[2] + pad;
5083
5084         // return true if eye overlaps enlarged box
5085         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5086                 return true;
5087
5088         // try specific positions in the box first - note that these can be cached
5089         if (r_cullentities_trace_entityocclusion.integer)
5090         {
5091                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5092                 {
5093                         VectorCopy(eye, start);
5094                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5095                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5096                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5097                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5098                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5099                         // not picky - if the trace ended anywhere in the box we're good
5100                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5101                                 return true;
5102                 }
5103         }
5104         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5105                 return true;
5106
5107         // try various random positions
5108         for (i = 0; i < numsamples; i++)
5109         {
5110                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5111                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5112                 if (r_cullentities_trace_entityocclusion.integer)
5113                 {
5114                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5115                         // not picky - if the trace ended anywhere in the box we're good
5116                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5117                                 return true;
5118                 }
5119                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5120                         return true;
5121         }
5122
5123         return false;
5124 }
5125
5126
5127 static void R_View_UpdateEntityVisible (void)
5128 {
5129         int i;
5130         int renderimask;
5131         int samples;
5132         entity_render_t *ent;
5133
5134         if (r_refdef.envmap || r_fb.water.hideplayer)
5135                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5136         else if (chase_active.integer || r_fb.water.renderingscene)
5137                 renderimask = RENDER_VIEWMODEL;
5138         else
5139                 renderimask = RENDER_EXTERIORMODEL;
5140         if (!r_drawviewmodel.integer)
5141                 renderimask |= RENDER_VIEWMODEL;
5142         if (!r_drawexteriormodel.integer)
5143                 renderimask |= RENDER_EXTERIORMODEL;
5144         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5145         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5146         {
5147                 // worldmodel can 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                         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))
5154                                 r_refdef.viewcache.entityvisible[i] = true;
5155                 }
5156         }
5157         else
5158         {
5159                 // no worldmodel or it can't check visibility
5160                 for (i = 0;i < r_refdef.scene.numentities;i++)
5161                 {
5162                         ent = r_refdef.scene.entities[i];
5163                         if (!(ent->flags & renderimask))
5164                         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)))
5165                                 r_refdef.viewcache.entityvisible[i] = true;
5166                 }
5167         }
5168         if (r_cullentities_trace.integer)
5169         {
5170                 for (i = 0;i < r_refdef.scene.numentities;i++)
5171                 {
5172                         if (!r_refdef.viewcache.entityvisible[i])
5173                                 continue;
5174                         ent = r_refdef.scene.entities[i];
5175                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5176                         {
5177                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5178                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_cullentities_trace_expand.value, r_cullentities_trace_pad.value, r_refdef.view.origin, ent->mins, ent->maxs))
5179                                         ent->last_trace_visibility = realtime;
5180                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5181                                         r_refdef.viewcache.entityvisible[i] = 0;
5182                         }
5183                 }
5184         }
5185 }
5186
5187 /// only used if skyrendermasked, and normally returns false
5188 static int R_DrawBrushModelsSky (void)
5189 {
5190         int i, sky;
5191         entity_render_t *ent;
5192
5193         sky = false;
5194         for (i = 0;i < r_refdef.scene.numentities;i++)
5195         {
5196                 if (!r_refdef.viewcache.entityvisible[i])
5197                         continue;
5198                 ent = r_refdef.scene.entities[i];
5199                 if (!ent->model || !ent->model->DrawSky)
5200                         continue;
5201                 ent->model->DrawSky(ent);
5202                 sky = true;
5203         }
5204         return sky;
5205 }
5206
5207 static void R_DrawNoModel(entity_render_t *ent);
5208 static void R_DrawModels(void)
5209 {
5210         int i;
5211         entity_render_t *ent;
5212
5213         for (i = 0;i < r_refdef.scene.numentities;i++)
5214         {
5215                 if (!r_refdef.viewcache.entityvisible[i])
5216                         continue;
5217                 ent = r_refdef.scene.entities[i];
5218                 r_refdef.stats[r_stat_entities]++;
5219                 /*
5220                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5221                 {
5222                         vec3_t f, l, u, o;
5223                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5224                         Con_Printf("R_DrawModels\n");
5225                         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]);
5226                         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);
5227                         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);
5228                 }
5229                 */
5230                 if (ent->model && ent->model->Draw != NULL)
5231                         ent->model->Draw(ent);
5232                 else
5233                         R_DrawNoModel(ent);
5234         }
5235 }
5236
5237 static void R_DrawModelsDepth(void)
5238 {
5239         int i;
5240         entity_render_t *ent;
5241
5242         for (i = 0;i < r_refdef.scene.numentities;i++)
5243         {
5244                 if (!r_refdef.viewcache.entityvisible[i])
5245                         continue;
5246                 ent = r_refdef.scene.entities[i];
5247                 if (ent->model && ent->model->DrawDepth != NULL)
5248                         ent->model->DrawDepth(ent);
5249         }
5250 }
5251
5252 static void R_DrawModelsDebug(void)
5253 {
5254         int i;
5255         entity_render_t *ent;
5256
5257         for (i = 0;i < r_refdef.scene.numentities;i++)
5258         {
5259                 if (!r_refdef.viewcache.entityvisible[i])
5260                         continue;
5261                 ent = r_refdef.scene.entities[i];
5262                 if (ent->model && ent->model->DrawDebug != NULL)
5263                         ent->model->DrawDebug(ent);
5264         }
5265 }
5266
5267 static void R_DrawModelsAddWaterPlanes(void)
5268 {
5269         int i;
5270         entity_render_t *ent;
5271
5272         for (i = 0;i < r_refdef.scene.numentities;i++)
5273         {
5274                 if (!r_refdef.viewcache.entityvisible[i])
5275                         continue;
5276                 ent = r_refdef.scene.entities[i];
5277                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5278                         ent->model->DrawAddWaterPlanes(ent);
5279         }
5280 }
5281
5282 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}};
5283
5284 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5285 {
5286         if (r_hdr_irisadaptation.integer)
5287         {
5288                 vec3_t p;
5289                 vec3_t ambient;
5290                 vec3_t diffuse;
5291                 vec3_t diffusenormal;
5292                 vec3_t forward;
5293                 vec_t brightness = 0.0f;
5294                 vec_t goal;
5295                 vec_t current;
5296                 vec_t d;
5297                 int c;
5298                 VectorCopy(r_refdef.view.forward, forward);
5299                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5300                 {
5301                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5302                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5303                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5304                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5305                         d = DotProduct(forward, diffusenormal);
5306                         brightness += VectorLength(ambient);
5307                         if (d > 0)
5308                                 brightness += d * VectorLength(diffuse);
5309                 }
5310                 brightness *= 1.0f / c;
5311                 brightness += 0.00001f; // make sure it's never zero
5312                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5313                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5314                 current = r_hdr_irisadaptation_value.value;
5315                 if (current < goal)
5316                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5317                 else if (current > goal)
5318                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5319                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5320                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5321         }
5322         else if (r_hdr_irisadaptation_value.value != 1.0f)
5323                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5324 }
5325
5326 static void R_View_SetFrustum(const int *scissor)
5327 {
5328         int i;
5329         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5330         vec3_t forward, left, up, origin, v;
5331
5332         if(scissor)
5333         {
5334                 // flipped x coordinates (because x points left here)
5335                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5336                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5337
5338                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5339                 switch(vid.renderpath)
5340                 {
5341                         case RENDERPATH_D3D9:
5342                         case RENDERPATH_D3D10:
5343                         case RENDERPATH_D3D11:
5344                                 // non-flipped y coordinates
5345                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5346                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5347                                 break;
5348                         case RENDERPATH_SOFT:
5349                         case RENDERPATH_GL11:
5350                         case RENDERPATH_GL13:
5351                         case RENDERPATH_GL20:
5352                         case RENDERPATH_GLES1:
5353                         case RENDERPATH_GLES2:
5354                                 // non-flipped y coordinates
5355                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5356                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5357                                 break;
5358                 }
5359         }
5360
5361         // we can't trust r_refdef.view.forward and friends in reflected scenes
5362         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5363
5364 #if 0
5365         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5366         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5367         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5368         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5369         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5370         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5371         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5372         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5373         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5374         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5375         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5376         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5377 #endif
5378
5379 #if 0
5380         zNear = r_refdef.nearclip;
5381         nudge = 1.0 - 1.0 / (1<<23);
5382         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5383         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5384         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5385         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5386         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5387         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5388         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5389         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5390 #endif
5391
5392
5393
5394 #if 0
5395         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5396         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5397         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5398         r_refdef.view.frustum[0].dist = m[15] - m[12];
5399
5400         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5401         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5402         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5403         r_refdef.view.frustum[1].dist = m[15] + m[12];
5404
5405         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5406         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5407         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5408         r_refdef.view.frustum[2].dist = m[15] - m[13];
5409
5410         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5411         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5412         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5413         r_refdef.view.frustum[3].dist = m[15] + m[13];
5414
5415         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5416         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5417         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5418         r_refdef.view.frustum[4].dist = m[15] - m[14];
5419
5420         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5421         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5422         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5423         r_refdef.view.frustum[5].dist = m[15] + m[14];
5424 #endif
5425
5426         if (r_refdef.view.useperspective)
5427         {
5428                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5429                 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]);
5430                 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]);
5431                 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]);
5432                 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]);
5433
5434                 // then the normals from the corners relative to origin
5435                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5436                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5437                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5438                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5439
5440                 // in a NORMAL view, forward cross left == up
5441                 // in a REFLECTED view, forward cross left == down
5442                 // so our cross products above need to be adjusted for a left handed coordinate system
5443                 CrossProduct(forward, left, v);
5444                 if(DotProduct(v, up) < 0)
5445                 {
5446                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5447                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5448                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5449                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5450                 }
5451
5452                 // Leaving those out was a mistake, those were in the old code, and they
5453                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5454                 // I couldn't reproduce it after adding those normalizations. --blub
5455                 VectorNormalize(r_refdef.view.frustum[0].normal);
5456                 VectorNormalize(r_refdef.view.frustum[1].normal);
5457                 VectorNormalize(r_refdef.view.frustum[2].normal);
5458                 VectorNormalize(r_refdef.view.frustum[3].normal);
5459
5460                 // make the corners absolute
5461                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5462                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5463                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5464                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5465
5466                 // one more normal
5467                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5468
5469                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5470                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5471                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5472                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5473                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5474         }
5475         else
5476         {
5477                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5478                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5479                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5480                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5481                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5482                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5483                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5484                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5485                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5486                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5487         }
5488         r_refdef.view.numfrustumplanes = 5;
5489
5490         if (r_refdef.view.useclipplane)
5491         {
5492                 r_refdef.view.numfrustumplanes = 6;
5493                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5494         }
5495
5496         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5497                 PlaneClassify(r_refdef.view.frustum + i);
5498
5499         // LordHavoc: note to all quake engine coders, Quake had a special case
5500         // for 90 degrees which assumed a square view (wrong), so I removed it,
5501         // Quake2 has it disabled as well.
5502
5503         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5504         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5505         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5506         //PlaneClassify(&frustum[0]);
5507
5508         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5509         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5510         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5511         //PlaneClassify(&frustum[1]);
5512
5513         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5514         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5515         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5516         //PlaneClassify(&frustum[2]);
5517
5518         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5519         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5520         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5521         //PlaneClassify(&frustum[3]);
5522
5523         // nearclip plane
5524         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5525         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5526         //PlaneClassify(&frustum[4]);
5527 }
5528
5529 static void R_View_UpdateWithScissor(const int *myscissor)
5530 {
5531         R_Main_ResizeViewCache();
5532         R_View_SetFrustum(myscissor);
5533         R_View_WorldVisibility(r_refdef.view.useclipplane);
5534         R_View_UpdateEntityVisible();
5535 }
5536
5537 static void R_View_Update(void)
5538 {
5539         R_Main_ResizeViewCache();
5540         R_View_SetFrustum(NULL);
5541         R_View_WorldVisibility(r_refdef.view.useclipplane);
5542         R_View_UpdateEntityVisible();
5543 }
5544
5545 float viewscalefpsadjusted = 1.0f;
5546
5547 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5548 {
5549         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5550         scale = bound(0.03125f, scale, 1.0f);
5551         *outwidth = (int)ceil(width * scale);
5552         *outheight = (int)ceil(height * scale);
5553 }
5554
5555 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5556 {
5557         const float *customclipplane = NULL;
5558         float plane[4];
5559         int /*rtwidth,*/ rtheight;
5560         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5561         {
5562                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5563                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5564                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5565                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5566                         dist = r_refdef.view.clipplane.dist;
5567                 plane[0] = r_refdef.view.clipplane.normal[0];
5568                 plane[1] = r_refdef.view.clipplane.normal[1];
5569                 plane[2] = r_refdef.view.clipplane.normal[2];
5570                 plane[3] = -dist;
5571                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5572         }
5573
5574         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5575         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5576
5577         if (!r_refdef.view.useperspective)
5578                 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);
5579         else if (vid.stencil && r_useinfinitefarclip.integer)
5580                 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);
5581         else
5582                 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);
5583         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5584         R_SetViewport(&r_refdef.view.viewport);
5585         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5586         {
5587                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5588                 float screenplane[4];
5589                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5590                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5591                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5592                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5593                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5594         }
5595 }
5596
5597 void R_EntityMatrix(const matrix4x4_t *matrix)
5598 {
5599         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5600         {
5601                 gl_modelmatrixchanged = false;
5602                 gl_modelmatrix = *matrix;
5603                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5604                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5605                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5606                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5607                 CHECKGLERROR
5608                 switch(vid.renderpath)
5609                 {
5610                 case RENDERPATH_D3D9:
5611 #ifdef SUPPORTD3D
5612                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5613                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5614 #endif
5615                         break;
5616                 case RENDERPATH_D3D10:
5617                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5618                         break;
5619                 case RENDERPATH_D3D11:
5620                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5621                         break;
5622                 case RENDERPATH_GL11:
5623                 case RENDERPATH_GL13:
5624                 case RENDERPATH_GLES1:
5625 #ifndef USE_GLES2
5626                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5627 #endif
5628                         break;
5629                 case RENDERPATH_SOFT:
5630                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5631                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5632                         break;
5633                 case RENDERPATH_GL20:
5634                 case RENDERPATH_GLES2:
5635                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5636                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5637                         break;
5638                 }
5639         }
5640 }
5641
5642 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5643 {
5644         r_viewport_t viewport;
5645
5646         CHECKGLERROR
5647
5648         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5649         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5650         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5651         R_SetViewport(&viewport);
5652         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5653         GL_Color(1, 1, 1, 1);
5654         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5655         GL_BlendFunc(GL_ONE, GL_ZERO);
5656         GL_ScissorTest(false);
5657         GL_DepthMask(false);
5658         GL_DepthRange(0, 1);
5659         GL_DepthTest(false);
5660         GL_DepthFunc(GL_LEQUAL);
5661         R_EntityMatrix(&identitymatrix);
5662         R_Mesh_ResetTextureState();
5663         GL_PolygonOffset(0, 0);
5664         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5665         switch(vid.renderpath)
5666         {
5667         case RENDERPATH_GL11:
5668         case RENDERPATH_GL13:
5669         case RENDERPATH_GL20:
5670         case RENDERPATH_GLES1:
5671         case RENDERPATH_GLES2:
5672                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5673                 break;
5674         case RENDERPATH_D3D9:
5675         case RENDERPATH_D3D10:
5676         case RENDERPATH_D3D11:
5677         case RENDERPATH_SOFT:
5678                 break;
5679         }
5680         GL_CullFace(GL_NONE);
5681
5682         CHECKGLERROR
5683 }
5684
5685 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5686 {
5687         DrawQ_Finish();
5688
5689         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5690 }
5691
5692 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5693 {
5694         DrawQ_Finish();
5695
5696         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5697         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5698         GL_Color(1, 1, 1, 1);
5699         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5700         GL_BlendFunc(GL_ONE, GL_ZERO);
5701         GL_ScissorTest(true);
5702         GL_DepthMask(true);
5703         GL_DepthRange(0, 1);
5704         GL_DepthTest(true);
5705         GL_DepthFunc(GL_LEQUAL);
5706         R_EntityMatrix(&identitymatrix);
5707         R_Mesh_ResetTextureState();
5708         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5709         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5710         switch(vid.renderpath)
5711         {
5712         case RENDERPATH_GL11:
5713         case RENDERPATH_GL13:
5714         case RENDERPATH_GL20:
5715         case RENDERPATH_GLES1:
5716         case RENDERPATH_GLES2:
5717                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5718                 break;
5719         case RENDERPATH_D3D9:
5720         case RENDERPATH_D3D10:
5721         case RENDERPATH_D3D11:
5722         case RENDERPATH_SOFT:
5723                 break;
5724         }
5725         GL_CullFace(r_refdef.view.cullface_back);
5726 }
5727
5728 /*
5729 ================
5730 R_RenderView_UpdateViewVectors
5731 ================
5732 */
5733 void R_RenderView_UpdateViewVectors(void)
5734 {
5735         // break apart the view matrix into vectors for various purposes
5736         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5737         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5738         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5739         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5740         // make an inverted copy of the view matrix for tracking sprites
5741         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5742 }
5743
5744 void R_RenderTarget_FreeUnused(qboolean force)
5745 {
5746         int i, j, end;
5747         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5748         for (i = 0; i < end; i++)
5749         {
5750                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5751                 // free resources for rendertargets that have not been used for a while
5752                 // (note: this check is run after the frame render, so any targets used
5753                 // this frame will not be affected even at low framerates)
5754                 if (r && (realtime - r->lastusetime > 0.2 || force))
5755                 {
5756                         if (r->fbo)
5757                                 R_Mesh_DestroyFramebufferObject(r->fbo);
5758                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5759                                 if (r->colortexture[j])
5760                                         R_FreeTexture(r->colortexture[j]);
5761                         if (r->depthtexture)
5762                                 R_FreeTexture(r->depthtexture);
5763                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5764                 }
5765         }
5766 }
5767
5768 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5769 {
5770         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5771         switch (vid.renderpath)
5772         {
5773         case RENDERPATH_D3D9:
5774                 x1 = (x + 0.5f) * iw;
5775                 x2 = (x + 0.5f + w) * iw;
5776                 y1 = (y + 0.5f) * ih;
5777                 y2 = (y + 0.5f + h) * ih;
5778                 break;
5779         default:
5780                 x1 = x * iw;
5781                 x2 = (x + w) * iw;
5782                 y1 = (th - y) * ih;
5783                 y2 = (th - y - h) * ih;
5784                 break;
5785         }
5786         texcoord2f[0] = x1;
5787         texcoord2f[2] = x2;
5788         texcoord2f[4] = x2;
5789         texcoord2f[6] = x1;
5790         texcoord2f[1] = y1;
5791         texcoord2f[3] = y1;
5792         texcoord2f[5] = y2;
5793         texcoord2f[7] = y2;
5794 }
5795
5796 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5797 {
5798         int i, j, end;
5799         r_rendertarget_t *r = NULL;
5800         char vabuf[256];
5801         // first try to reuse an existing slot if possible
5802         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5803         for (i = 0; i < end; i++)
5804         {
5805                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5806                 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5807                         break;
5808         }
5809         if (i == end)
5810         {
5811                 // no unused exact match found, so we have to make one in the first unused slot
5812                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5813                 r->texturewidth = texturewidth;
5814                 r->textureheight = textureheight;
5815                 r->colortextype[0] = colortextype0;
5816                 r->colortextype[1] = colortextype1;
5817                 r->colortextype[2] = colortextype2;
5818                 r->colortextype[3] = colortextype3;
5819                 r->depthtextype = depthtextype;
5820                 r->depthisrenderbuffer = depthisrenderbuffer;
5821                 for (j = 0; j < 4; j++)
5822                         if (r->colortextype[j])
5823                                 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5824                 if (r->depthtextype)
5825                 {
5826                         if (r->depthisrenderbuffer)
5827                                 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5828                         else
5829                                 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5830                 }
5831                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5832         }
5833         r_refdef.stats[r_stat_rendertargets_used]++;
5834         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5835         r->lastusetime = realtime;
5836         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5837         return r;
5838 }
5839
5840 static void R_Water_StartFrame(void)
5841 {
5842         int waterwidth, waterheight;
5843
5844         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5845                 return;
5846
5847         switch(vid.renderpath)
5848         {
5849         case RENDERPATH_GL20:
5850         case RENDERPATH_D3D9:
5851         case RENDERPATH_D3D10:
5852         case RENDERPATH_D3D11:
5853         case RENDERPATH_SOFT:
5854         case RENDERPATH_GLES2:
5855                 break;
5856         case RENDERPATH_GL11:
5857         case RENDERPATH_GL13:
5858         case RENDERPATH_GLES1:
5859                 return;
5860         }
5861
5862         // set waterwidth and waterheight to the water resolution that will be
5863         // used (often less than the screen resolution for faster rendering)
5864         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5865         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5866         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5867
5868         if (!r_water.integer || r_showsurfaces.integer)
5869                 waterwidth = waterheight = 0;
5870
5871         // set up variables that will be used in shader setup
5872         r_fb.water.waterwidth = waterwidth;
5873         r_fb.water.waterheight = waterheight;
5874         r_fb.water.texturewidth = waterwidth;
5875         r_fb.water.textureheight = waterheight;
5876         r_fb.water.camerawidth = waterwidth;
5877         r_fb.water.cameraheight = waterheight;
5878         r_fb.water.screenscale[0] = 0.5f;
5879         r_fb.water.screenscale[1] = 0.5f;
5880         r_fb.water.screencenter[0] = 0.5f;
5881         r_fb.water.screencenter[1] = 0.5f;
5882         r_fb.water.enabled = waterwidth != 0;
5883
5884         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5885         r_fb.water.numwaterplanes = 0;
5886 }
5887
5888 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5889 {
5890         int planeindex, bestplaneindex, vertexindex;
5891         vec3_t mins, maxs, normal, center, v, n;
5892         vec_t planescore, bestplanescore;
5893         mplane_t plane;
5894         r_waterstate_waterplane_t *p;
5895         texture_t *t = R_GetCurrentTexture(surface->texture);
5896
5897         rsurface.texture = t;
5898         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5899         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5900         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5901                 return;
5902         // average the vertex normals, find the surface bounds (after deformvertexes)
5903         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5904         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5905         VectorCopy(n, normal);
5906         VectorCopy(v, mins);
5907         VectorCopy(v, maxs);
5908         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5909         {
5910                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5911                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5912                 VectorAdd(normal, n, normal);
5913                 mins[0] = min(mins[0], v[0]);
5914                 mins[1] = min(mins[1], v[1]);
5915                 mins[2] = min(mins[2], v[2]);
5916                 maxs[0] = max(maxs[0], v[0]);
5917                 maxs[1] = max(maxs[1], v[1]);
5918                 maxs[2] = max(maxs[2], v[2]);
5919         }
5920         VectorNormalize(normal);
5921         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5922
5923         VectorCopy(normal, plane.normal);
5924         VectorNormalize(plane.normal);
5925         plane.dist = DotProduct(center, plane.normal);
5926         PlaneClassify(&plane);
5927         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5928         {
5929                 // skip backfaces (except if nocullface is set)
5930 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5931 //                      return;
5932                 VectorNegate(plane.normal, plane.normal);
5933                 plane.dist *= -1;
5934                 PlaneClassify(&plane);
5935         }
5936
5937
5938         // find a matching plane if there is one
5939         bestplaneindex = -1;
5940         bestplanescore = 1048576.0f;
5941         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5942         {
5943                 if(p->camera_entity == t->camera_entity)
5944                 {
5945                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5946                         if (bestplaneindex < 0 || bestplanescore > planescore)
5947                         {
5948                                 bestplaneindex = planeindex;
5949                                 bestplanescore = planescore;
5950                         }
5951                 }
5952         }
5953         planeindex = bestplaneindex;
5954
5955         // if this surface does not fit any known plane rendered this frame, add one
5956         if (planeindex < 0 || bestplanescore > 0.001f)
5957         {
5958                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5959                 {
5960                         // store the new plane
5961                         planeindex = r_fb.water.numwaterplanes++;
5962                         p = r_fb.water.waterplanes + planeindex;
5963                         p->plane = plane;
5964                         // clear materialflags and pvs
5965                         p->materialflags = 0;
5966                         p->pvsvalid = false;
5967                         p->camera_entity = t->camera_entity;
5968                         VectorCopy(mins, p->mins);
5969                         VectorCopy(maxs, p->maxs);
5970                 }
5971                 else
5972                 {
5973                         // We're totally screwed.
5974                         return;
5975                 }
5976         }
5977         else
5978         {
5979                 // merge mins/maxs when we're adding this surface to the plane
5980                 p = r_fb.water.waterplanes + planeindex;
5981                 p->mins[0] = min(p->mins[0], mins[0]);
5982                 p->mins[1] = min(p->mins[1], mins[1]);
5983                 p->mins[2] = min(p->mins[2], mins[2]);
5984                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5985                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5986                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5987         }
5988         // merge this surface's materialflags into the waterplane
5989         p->materialflags |= t->currentmaterialflags;
5990         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5991         {
5992                 // merge this surface's PVS into the waterplane
5993                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5994                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5995                 {
5996                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5997                         p->pvsvalid = true;
5998                 }
5999         }
6000 }
6001
6002 extern cvar_t r_drawparticles;
6003 extern cvar_t r_drawdecals;
6004
6005 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
6006 {
6007         int myscissor[4];
6008         r_refdef_view_t originalview;
6009         r_refdef_view_t myview;
6010         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
6011         r_waterstate_waterplane_t *p;
6012         vec3_t visorigin;
6013         r_rendertarget_t *rt;
6014
6015         originalview = r_refdef.view;
6016
6017         // lowquality hack, temporarily shut down some cvars and restore afterwards
6018         qualityreduction = r_water_lowquality.integer;
6019         if (qualityreduction > 0)
6020         {
6021                 if (qualityreduction >= 1)
6022                 {
6023                         old_r_shadows = r_shadows.integer;
6024                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6025                         old_r_dlight = r_shadow_realtime_dlight.integer;
6026                         Cvar_SetValueQuick(&r_shadows, 0);
6027                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6028                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6029                 }
6030                 if (qualityreduction >= 2)
6031                 {
6032                         old_r_dynamic = r_dynamic.integer;
6033                         old_r_particles = r_drawparticles.integer;
6034                         old_r_decals = r_drawdecals.integer;
6035                         Cvar_SetValueQuick(&r_dynamic, 0);
6036                         Cvar_SetValueQuick(&r_drawparticles, 0);
6037                         Cvar_SetValueQuick(&r_drawdecals, 0);
6038                 }
6039         }
6040
6041         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6042         {
6043                 p->rt_reflection = NULL;
6044                 p->rt_refraction = NULL;
6045                 p->rt_camera = NULL;
6046         }
6047
6048         // render views
6049         r_refdef.view = originalview;
6050         r_refdef.view.showdebug = false;
6051         r_refdef.view.width = r_fb.water.waterwidth;
6052         r_refdef.view.height = r_fb.water.waterheight;
6053         r_refdef.view.useclipplane = true;
6054         myview = r_refdef.view;
6055         r_fb.water.renderingscene = true;
6056         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6057         {
6058                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6059                         continue;
6060
6061                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6062                 {
6063                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6064                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6065                                 goto error;
6066                         r_refdef.view = myview;
6067                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6068                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6069                         if(r_water_scissormode.integer)
6070                         {
6071                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6072                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6073                                 {
6074                                         p->rt_reflection = NULL;
6075                                         p->rt_refraction = NULL;
6076                                         p->rt_camera = NULL;
6077                                         continue;
6078                                 }
6079                         }
6080
6081                         r_refdef.view.clipplane = p->plane;
6082                         // reverse the cullface settings for this render
6083                         r_refdef.view.cullface_front = GL_FRONT;
6084                         r_refdef.view.cullface_back = GL_BACK;
6085                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6086                         {
6087                                 r_refdef.view.usecustompvs = true;
6088                                 if (p->pvsvalid)
6089                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6090                                 else
6091                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6092                         }
6093
6094                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6095                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6096                         GL_ScissorTest(false);
6097                         R_ClearScreen(r_refdef.fogenabled);
6098                         GL_ScissorTest(true);
6099                         if(r_water_scissormode.integer & 2)
6100                                 R_View_UpdateWithScissor(myscissor);
6101                         else
6102                                 R_View_Update();
6103                         R_AnimCache_CacheVisibleEntities();
6104                         if(r_water_scissormode.integer & 1)
6105                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6106                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6107
6108                         r_fb.water.hideplayer = false;
6109                         p->rt_reflection = rt;
6110                 }
6111
6112                 // render the normal view scene and copy into texture
6113                 // (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)
6114                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6115                 {
6116                         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);
6117                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6118                                 goto error;
6119                         r_refdef.view = myview;
6120                         if(r_water_scissormode.integer)
6121                         {
6122                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6123                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6124                                 {
6125                                         p->rt_reflection = NULL;
6126                                         p->rt_refraction = NULL;
6127                                         p->rt_camera = NULL;
6128                                         continue;
6129                                 }
6130                         }
6131
6132                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6133
6134                         r_refdef.view.clipplane = p->plane;
6135                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6136                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6137
6138                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6139                         {
6140                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6141                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6142                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6143                                 R_RenderView_UpdateViewVectors();
6144                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6145                                 {
6146                                         r_refdef.view.usecustompvs = true;
6147                                         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);
6148                                 }
6149                         }
6150
6151                         PlaneClassify(&r_refdef.view.clipplane);
6152
6153                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6154                         GL_ScissorTest(false);
6155                         R_ClearScreen(r_refdef.fogenabled);
6156                         GL_ScissorTest(true);
6157                         if(r_water_scissormode.integer & 2)
6158                                 R_View_UpdateWithScissor(myscissor);
6159                         else
6160                                 R_View_Update();
6161                         R_AnimCache_CacheVisibleEntities();
6162                         if(r_water_scissormode.integer & 1)
6163                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6164                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6165
6166                         r_fb.water.hideplayer = false;
6167                         p->rt_refraction = rt;
6168                 }
6169                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6170                 {
6171                         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);
6172                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6173                                 goto error;
6174                         r_refdef.view = myview;
6175
6176                         r_refdef.view.clipplane = p->plane;
6177                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6178                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6179
6180                         r_refdef.view.width = r_fb.water.camerawidth;
6181                         r_refdef.view.height = r_fb.water.cameraheight;
6182                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6183                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6184                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6185                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6186
6187                         if(p->camera_entity)
6188                         {
6189                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6190                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6191                         }
6192
6193                         // note: all of the view is used for displaying... so
6194                         // there is no use in scissoring
6195
6196                         // reverse the cullface settings for this render
6197                         r_refdef.view.cullface_front = GL_FRONT;
6198                         r_refdef.view.cullface_back = GL_BACK;
6199                         // also reverse the view matrix
6200                         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
6201                         R_RenderView_UpdateViewVectors();
6202                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6203                         {
6204                                 r_refdef.view.usecustompvs = true;
6205                                 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);
6206                         }
6207                         
6208                         // camera needs no clipplane
6209                         r_refdef.view.useclipplane = false;
6210
6211                         PlaneClassify(&r_refdef.view.clipplane);
6212
6213                         r_fb.water.hideplayer = false;
6214
6215                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6216                         GL_ScissorTest(false);
6217                         R_ClearScreen(r_refdef.fogenabled);
6218                         GL_ScissorTest(true);
6219                         R_View_Update();
6220                         R_AnimCache_CacheVisibleEntities();
6221                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6222
6223                         r_fb.water.hideplayer = false;
6224                         p->rt_camera = rt;
6225                 }
6226
6227         }
6228         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6229         r_fb.water.renderingscene = false;
6230         r_refdef.view = originalview;
6231         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6232         R_View_Update();
6233         R_AnimCache_CacheVisibleEntities();
6234         goto finish;
6235 error:
6236         r_refdef.view = originalview;
6237         r_fb.water.renderingscene = false;
6238         Cvar_SetValueQuick(&r_water, 0);
6239         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6240 finish:
6241         // lowquality hack, restore cvars
6242         if (qualityreduction > 0)
6243         {
6244                 if (qualityreduction >= 1)
6245                 {
6246                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6247                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6248                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6249                 }
6250                 if (qualityreduction >= 2)
6251                 {
6252                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6253                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6254                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6255                 }
6256         }
6257 }
6258
6259 static void R_Bloom_StartFrame(void)
6260 {
6261         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6262         int viewwidth, viewheight;
6263         textype_t textype = TEXTYPE_COLORBUFFER;
6264
6265         // clear the pointers to rendertargets from last frame as they're stale
6266         r_fb.rt_screen = NULL;
6267         r_fb.rt_bloom = NULL;
6268
6269         switch (vid.renderpath)
6270         {
6271         case RENDERPATH_GL20:
6272                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6274                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6275                 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6276                 if (!vid.support.ext_framebuffer_object)
6277                         return;
6278                 break;
6279         case RENDERPATH_GL11:
6280         case RENDERPATH_GL13:
6281         case RENDERPATH_GLES1:
6282                 return; // don't bother
6283         case RENDERPATH_GLES2:
6284         case RENDERPATH_D3D9:
6285         case RENDERPATH_D3D10:
6286         case RENDERPATH_D3D11:
6287                 r_fb.usedepthtextures = false;
6288                 break;
6289         case RENDERPATH_SOFT:
6290                 r_fb.usedepthtextures = true;
6291                 break;
6292         }
6293
6294         if (r_viewscale_fpsscaling.integer)
6295         {
6296                 double actualframetime;
6297                 double targetframetime;
6298                 double adjust;
6299                 actualframetime = r_refdef.lastdrawscreentime;
6300                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6301                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6302                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6303                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6304                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6305                 viewscalefpsadjusted += adjust;
6306                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6307         }
6308         else
6309                 viewscalefpsadjusted = 1.0f;
6310
6311         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6312
6313         // set bloomwidth and bloomheight to the bloom resolution that will be
6314         // used (often less than the screen resolution for faster rendering)
6315         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6316         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6317         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6318         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6319         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6320
6321         // calculate desired texture sizes
6322         screentexturewidth = viewwidth;
6323         screentextureheight = viewheight;
6324         bloomtexturewidth = r_fb.bloomwidth;
6325         bloomtextureheight = r_fb.bloomheight;
6326
6327         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))
6328         {
6329                 Cvar_SetValueQuick(&r_bloom, 0);
6330                 Cvar_SetValueQuick(&r_motionblur, 0);
6331                 Cvar_SetValueQuick(&r_damageblur, 0);
6332         }
6333
6334         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6335         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6336         {
6337                 if (r_fb.ghosttexture)
6338                         R_FreeTexture(r_fb.ghosttexture);
6339                 r_fb.ghosttexture = NULL;
6340
6341                 r_fb.screentexturewidth = screentexturewidth;
6342                 r_fb.screentextureheight = screentextureheight;
6343                 r_fb.textype = textype;
6344
6345                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6346                 {
6347                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6348                                 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);
6349                         r_fb.ghosttexture_valid = false;
6350                 }
6351         }
6352
6353         if (r_bloom.integer)
6354         {
6355                 // bloom texture is a different resolution
6356                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6357                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6358                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6359         }
6360         else
6361                 r_fb.bloomwidth = r_fb.bloomheight = 0;
6362
6363         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6364
6365         r_refdef.view.clear = true;
6366 }
6367
6368 static void R_Bloom_MakeTexture(void)
6369 {
6370         int x, range, dir;
6371         float xoffset, yoffset, r, brighten;
6372         float colorscale = r_bloom_colorscale.value;
6373         r_viewport_t bloomviewport;
6374         r_rendertarget_t *prev, *cur;
6375         textype_t textype = r_fb.rt_screen->colortextype[0];
6376
6377         r_refdef.stats[r_stat_bloom]++;
6378
6379         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6380
6381         // scale down screen texture to the bloom texture size
6382         CHECKGLERROR
6383         prev = r_fb.rt_screen;
6384         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6385         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6386         R_SetViewport(&bloomviewport);
6387         GL_CullFace(GL_NONE);
6388         GL_DepthTest(false);
6389         GL_BlendFunc(GL_ONE, GL_ZERO);
6390         GL_Color(colorscale, colorscale, colorscale, 1);
6391         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6392         // TODO: do boxfilter scale-down in shader?
6393         R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6394         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6395         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6396         // we now have a properly scaled bloom image
6397
6398         // multiply bloom image by itself as many times as desired to darken it
6399         // TODO: if people actually use this it could be done more quickly in the previous shader pass
6400         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6401         {
6402                 prev = cur;
6403                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6404                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6405                 x *= 2;
6406                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6407                 if(x <= 2)
6408                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6409                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6410                 GL_Color(1,1,1,1); // no fix factor supported here
6411                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6412                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6413                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6414                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6415         }
6416
6417         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6418         brighten = r_bloom_brighten.value;
6419         brighten = sqrt(brighten);
6420         if(range >= 1)
6421                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6422
6423         for (dir = 0;dir < 2;dir++)
6424         {
6425                 prev = cur;
6426                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6427                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6428                 // blend on at multiple vertical offsets to achieve a vertical blur
6429                 // TODO: do offset blends using GLSL
6430                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6431                 GL_BlendFunc(GL_ONE, GL_ZERO);
6432                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6433                 for (x = -range;x <= range;x++)
6434                 {
6435                         if (!dir){xoffset = 0;yoffset = x;}
6436                         else {xoffset = x;yoffset = 0;}
6437                         xoffset /= (float)prev->texturewidth;
6438                         yoffset /= (float)prev->textureheight;
6439                         // compute a texcoord array with the specified x and y offset
6440                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6441                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6442                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6443                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6444                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6445                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6446                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6447                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6448                         // this r value looks like a 'dot' particle, fading sharply to
6449                         // black at the edges
6450                         // (probably not realistic but looks good enough)
6451                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6452                         //r = brighten/(range*2+1);
6453                         r = brighten / (range * 2 + 1);
6454                         if(range >= 1)
6455                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
6456                         if (r <= 0)
6457                                 continue;
6458                         GL_Color(r, r, r, 1);
6459                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6460                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6461                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6462                         GL_BlendFunc(GL_ONE, GL_ONE);
6463                 }
6464         }
6465
6466         // now we have the bloom image, so keep track of it
6467         r_fb.rt_bloom = cur;
6468 }
6469
6470 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6471 {
6472         dpuint64 permutation;
6473         float uservecs[4][4];
6474         rtexture_t *viewtexture;
6475         rtexture_t *bloomtexture;
6476
6477         R_EntityMatrix(&identitymatrix);
6478
6479         switch (vid.renderpath)
6480         {
6481         case RENDERPATH_GL20:
6482         case RENDERPATH_D3D9:
6483         case RENDERPATH_D3D10:
6484         case RENDERPATH_D3D11:
6485         case RENDERPATH_SOFT:
6486         case RENDERPATH_GLES2:
6487                 permutation =
6488                           (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6489                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6490                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6491                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6492                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6493
6494                 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6495                 {
6496                         // declare variables
6497                         float blur_factor, blur_mouseaccel, blur_velocity;
6498                         static float blur_average; 
6499                         static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6500
6501                         // set a goal for the factoring
6502                         blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6503                                 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6504                         blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6505                                 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6506                         blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6507                                 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6508
6509                         // from the goal, pick an averaged value between goal and last value
6510                         cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6511                         blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6512
6513                         // enforce minimum amount of blur 
6514                         blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6515
6516                         //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6517
6518                         // calculate values into a standard alpha
6519                         cl.motionbluralpha = 1 - exp(-
6520                                         (
6521                                                 (r_motionblur.value * blur_factor / 80)
6522                                                 +
6523                                                 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6524                                         )
6525                                         /
6526                                         max(0.0001, cl.time - cl.oldtime) // fps independent
6527                                         );
6528
6529                         // randomization for the blur value to combat persistent ghosting
6530                         cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6531                         cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6532
6533                         // apply the blur
6534                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6535                         if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6536                         {
6537                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6538                                 GL_Color(1, 1, 1, cl.motionbluralpha);
6539                                 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6540                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6541                                 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6542                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6543                                 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6544                         }
6545
6546                         // updates old view angles for next pass
6547                         VectorCopy(cl.viewangles, blur_oldangles);
6548
6549                         // copy view into the ghost texture
6550                         R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6551                         r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6552                         r_fb.ghosttexture_valid = true;
6553                 }
6554
6555                 if (r_fb.bloomwidth)
6556                 {
6557                         // make the bloom texture
6558                         R_Bloom_MakeTexture();
6559                 }
6560
6561 #if _MSC_VER >= 1400
6562 #define sscanf sscanf_s
6563 #endif
6564                 memset(uservecs, 0, sizeof(uservecs));
6565                 if (r_glsl_postprocess_uservec1_enable.integer)
6566                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6567                 if (r_glsl_postprocess_uservec2_enable.integer)
6568                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6569                 if (r_glsl_postprocess_uservec3_enable.integer)
6570                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6571                 if (r_glsl_postprocess_uservec4_enable.integer)
6572                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6573
6574                 // render to the screen fbo
6575                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6576                 GL_Color(1, 1, 1, 1);
6577                 GL_BlendFunc(GL_ONE, GL_ZERO);
6578
6579                 viewtexture = r_fb.rt_screen->colortexture[0];
6580                 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6581
6582                 if (r_rendertarget_debug.integer >= 0)
6583                 {
6584                         r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6585                         if (rt && rt->colortexture[0])
6586                         {
6587                                 viewtexture = rt->colortexture[0];
6588                                 bloomtexture = NULL;
6589                         }
6590                 }
6591
6592                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6593                 switch(vid.renderpath)
6594                 {
6595                 case RENDERPATH_GL20:
6596                 case RENDERPATH_GLES2:
6597                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6598                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
6599                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
6600                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6601                         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]);
6602                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6603                         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]);
6604                         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]);
6605                         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]);
6606                         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]);
6607                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6608                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6609                         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);
6610                         break;
6611                 case RENDERPATH_D3D9:
6612 #ifdef SUPPORTD3D
6613                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6614                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6615                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6616                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6617                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6618                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6619                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6620                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6621                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6622                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6623                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6624                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6625                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6626 #endif
6627                         break;
6628                 case RENDERPATH_D3D10:
6629                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6630                         break;
6631                 case RENDERPATH_D3D11:
6632                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6633                         break;
6634                 case RENDERPATH_SOFT:
6635                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6636                         R_Mesh_TexBind(GL20TU_FIRST     , viewtexture);
6637                         R_Mesh_TexBind(GL20TU_SECOND    , bloomtexture);
6638                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6639                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6640                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6641                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6642                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6643                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6644                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6645                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6646                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6647                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6648                         break;
6649                 default:
6650                         break;
6651                 }
6652                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6653                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6654                 break;
6655         case RENDERPATH_GL11:
6656         case RENDERPATH_GL13:
6657         case RENDERPATH_GLES1:
6658                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6659                 {
6660                         // apply a color tint to the whole view
6661                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6662                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6663                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6664                         R_SetupShader_Generic_NoTexture(false, true);
6665                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6666                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6667                 }
6668                 break;
6669         }
6670 }
6671
6672 matrix4x4_t r_waterscrollmatrix;
6673
6674 void R_UpdateFog(void)
6675 {
6676         // Nehahra fog
6677         if (gamemode == GAME_NEHAHRA)
6678         {
6679                 if (gl_fogenable.integer)
6680                 {
6681                         r_refdef.oldgl_fogenable = true;
6682                         r_refdef.fog_density = gl_fogdensity.value;
6683                         r_refdef.fog_red = gl_fogred.value;
6684                         r_refdef.fog_green = gl_foggreen.value;
6685                         r_refdef.fog_blue = gl_fogblue.value;
6686                         r_refdef.fog_alpha = 1;
6687                         r_refdef.fog_start = 0;
6688                         r_refdef.fog_end = gl_skyclip.value;
6689                         r_refdef.fog_height = 1<<30;
6690                         r_refdef.fog_fadedepth = 128;
6691                 }
6692                 else if (r_refdef.oldgl_fogenable)
6693                 {
6694                         r_refdef.oldgl_fogenable = false;
6695                         r_refdef.fog_density = 0;
6696                         r_refdef.fog_red = 0;
6697                         r_refdef.fog_green = 0;
6698                         r_refdef.fog_blue = 0;
6699                         r_refdef.fog_alpha = 0;
6700                         r_refdef.fog_start = 0;
6701                         r_refdef.fog_end = 0;
6702                         r_refdef.fog_height = 1<<30;
6703                         r_refdef.fog_fadedepth = 128;
6704                 }
6705         }
6706
6707         // fog parms
6708         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6709         r_refdef.fog_start = max(0, r_refdef.fog_start);
6710         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6711
6712         if (r_refdef.fog_density && r_drawfog.integer)
6713         {
6714                 r_refdef.fogenabled = true;
6715                 // this is the point where the fog reaches 0.9986 alpha, which we
6716                 // consider a good enough cutoff point for the texture
6717                 // (0.9986 * 256 == 255.6)
6718                 if (r_fog_exp2.integer)
6719                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6720                 else
6721                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6722                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6723                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6724                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6725                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6726                         R_BuildFogHeightTexture();
6727                 // fog color was already set
6728                 // update the fog texture
6729                 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)
6730                         R_BuildFogTexture();
6731                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6732                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6733         }
6734         else
6735                 r_refdef.fogenabled = false;
6736
6737         // fog color
6738         if (r_refdef.fog_density)
6739         {
6740                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6741                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6742                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6743
6744                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6745                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6746                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6747                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6748
6749                 {
6750                         vec3_t fogvec;
6751                         VectorCopy(r_refdef.fogcolor, fogvec);
6752                         //   color.rgb *= ContrastBoost * SceneBrightness;
6753                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6754                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6755                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6756                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6757                 }
6758         }
6759 }
6760
6761 void R_UpdateVariables(void)
6762 {
6763         R_Textures_Frame();
6764
6765         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6766
6767         r_refdef.farclip = r_farclip_base.value;
6768         if (r_refdef.scene.worldmodel)
6769                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6770         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6771
6772         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6773                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6774         r_refdef.polygonfactor = 0;
6775         r_refdef.polygonoffset = 0;
6776         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6777         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6778
6779         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6780         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6781         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6782         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6783         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6784         if (FAKELIGHT_ENABLED)
6785         {
6786                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6787         }
6788         else if (r_refdef.scene.worldmodel)
6789         {
6790                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6791         }
6792         if (r_showsurfaces.integer)
6793         {
6794                 r_refdef.scene.rtworld = false;
6795                 r_refdef.scene.rtworldshadows = false;
6796                 r_refdef.scene.rtdlight = false;
6797                 r_refdef.scene.rtdlightshadows = false;
6798                 r_refdef.scene.lightmapintensity = 0;
6799         }
6800
6801         r_gpuskeletal = false;
6802         switch(vid.renderpath)
6803         {
6804         case RENDERPATH_GL20:
6805                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6806         case RENDERPATH_D3D9:
6807         case RENDERPATH_D3D10:
6808         case RENDERPATH_D3D11:
6809         case RENDERPATH_SOFT:
6810         case RENDERPATH_GLES2:
6811                 if(!vid_gammatables_trivial)
6812                 {
6813                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6814                         {
6815                                 // build GLSL gamma texture
6816 #define RAMPWIDTH 256
6817                                 unsigned short ramp[RAMPWIDTH * 3];
6818                                 unsigned char rampbgr[RAMPWIDTH][4];
6819                                 int i;
6820
6821                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6822
6823                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6824                                 for(i = 0; i < RAMPWIDTH; ++i)
6825                                 {
6826                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6827                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6828                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6829                                         rampbgr[i][3] = 0;
6830                                 }
6831                                 if (r_texture_gammaramps)
6832                                 {
6833                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6834                                 }
6835                                 else
6836                                 {
6837                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6838                                 }
6839                         }
6840                 }
6841                 else
6842                 {
6843                         // remove GLSL gamma texture
6844                 }
6845                 break;
6846         case RENDERPATH_GL11:
6847         case RENDERPATH_GL13:
6848         case RENDERPATH_GLES1:
6849                 break;
6850         }
6851 }
6852
6853 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6854 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6855 /*
6856 ================
6857 R_SelectScene
6858 ================
6859 */
6860 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6861         if( scenetype != r_currentscenetype ) {
6862                 // store the old scenetype
6863                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6864                 r_currentscenetype = scenetype;
6865                 // move in the new scene
6866                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6867         }
6868 }
6869
6870 /*
6871 ================
6872 R_GetScenePointer
6873 ================
6874 */
6875 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6876 {
6877         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6878         if( scenetype == r_currentscenetype ) {
6879                 return &r_refdef.scene;
6880         } else {
6881                 return &r_scenes_store[ scenetype ];
6882         }
6883 }
6884
6885 static int R_SortEntities_Compare(const void *ap, const void *bp)
6886 {
6887         const entity_render_t *a = *(const entity_render_t **)ap;
6888         const entity_render_t *b = *(const entity_render_t **)bp;
6889
6890         // 1. compare model
6891         if(a->model < b->model)
6892                 return -1;
6893         if(a->model > b->model)
6894                 return +1;
6895
6896         // 2. compare skin
6897         // TODO possibly calculate the REAL skinnum here first using
6898         // skinscenes?
6899         if(a->skinnum < b->skinnum)
6900                 return -1;
6901         if(a->skinnum > b->skinnum)
6902                 return +1;
6903
6904         // everything we compared is equal
6905         return 0;
6906 }
6907 static void R_SortEntities(void)
6908 {
6909         // below or equal 2 ents, sorting never gains anything
6910         if(r_refdef.scene.numentities <= 2)
6911                 return;
6912         // sort
6913         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6914 }
6915
6916 /*
6917 ================
6918 R_RenderView
6919 ================
6920 */
6921 int dpsoftrast_test;
6922 extern cvar_t r_shadow_bouncegrid;
6923 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6924 {
6925         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6926         int viewfbo = 0;
6927         rtexture_t *viewdepthtexture = NULL;
6928         rtexture_t *viewcolortexture = NULL;
6929         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6930
6931         dpsoftrast_test = r_test.integer;
6932
6933         if (r_timereport_active)
6934                 R_TimeReport("start");
6935         r_textureframe++; // used only by R_GetCurrentTexture
6936         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6937
6938         if(R_CompileShader_CheckStaticParms())
6939                 R_GLSL_Restart_f();
6940
6941         if (!r_drawentities.integer)
6942                 r_refdef.scene.numentities = 0;
6943         else if (r_sortentities.integer)
6944                 R_SortEntities();
6945
6946         R_AnimCache_ClearCache();
6947
6948         /* adjust for stereo display */
6949         if(R_Stereo_Active())
6950         {
6951                 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);
6952                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6953         }
6954
6955         if (r_refdef.view.isoverlay)
6956         {
6957                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6958                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6959                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6960                 R_TimeReport("depthclear");
6961
6962                 r_refdef.view.showdebug = false;
6963
6964                 r_fb.water.enabled = false;
6965                 r_fb.water.numwaterplanes = 0;
6966
6967                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6968
6969                 r_refdef.view.matrix = originalmatrix;
6970
6971                 CHECKGLERROR
6972                 return;
6973         }
6974
6975         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6976         {
6977                 r_refdef.view.matrix = originalmatrix;
6978                 return;
6979         }
6980
6981         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6982
6983         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6984                 // in sRGB fallback, behave similar to true sRGB: convert this
6985                 // value from linear to sRGB
6986                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6987
6988         R_RenderView_UpdateViewVectors();
6989
6990         R_Shadow_UpdateWorldLightSelection();
6991
6992         // this will set up r_fb.rt_screen
6993         R_Bloom_StartFrame();
6994
6995         // apply bloom brightness offset
6996         if(r_fb.rt_bloom)
6997                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6998
6999         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
7000         if (r_fb.rt_screen)
7001         {
7002                 viewfbo = r_fb.rt_screen->fbo;
7003                 viewdepthtexture = r_fb.rt_screen->depthtexture;
7004                 viewcolortexture = r_fb.rt_screen->colortexture[0];
7005                 viewx = 0;
7006                 viewy = 0;
7007                 viewwidth = width;
7008                 viewheight = height;
7009         }
7010
7011         R_Water_StartFrame();
7012
7013         CHECKGLERROR
7014         if (r_timereport_active)
7015                 R_TimeReport("viewsetup");
7016
7017         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7018
7019         // clear the whole fbo every frame - otherwise the driver will consider
7020         // it to be an inter-frame texture and stall in multi-gpu configurations
7021         if (r_fb.rt_screen)
7022                 GL_ScissorTest(false);
7023         R_ClearScreen(r_refdef.fogenabled);
7024         if (r_timereport_active)
7025                 R_TimeReport("viewclear");
7026
7027         r_refdef.view.clear = true;
7028
7029         r_refdef.view.showdebug = true;
7030
7031         R_View_Update();
7032         if (r_timereport_active)
7033                 R_TimeReport("visibility");
7034
7035         R_AnimCache_CacheVisibleEntities();
7036         if (r_timereport_active)
7037                 R_TimeReport("animcache");
7038
7039         R_Shadow_UpdateBounceGridTexture();
7040         if (r_timereport_active && r_shadow_bouncegrid.integer)
7041                 R_TimeReport("bouncegrid");
7042
7043         r_fb.water.numwaterplanes = 0;
7044         if (r_fb.water.enabled)
7045                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7046
7047         // for the actual view render we use scissoring a fair amount, so scissor
7048         // test needs to be on
7049         if (r_fb.rt_screen)
7050                 GL_ScissorTest(true);
7051         GL_Scissor(viewx, viewy, viewwidth, viewheight);
7052         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7053         r_fb.water.numwaterplanes = 0;
7054
7055         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7056         GL_ScissorTest(false);
7057
7058         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7059         if (r_timereport_active)
7060                 R_TimeReport("blendview");
7061
7062         r_refdef.view.matrix = originalmatrix;
7063
7064         CHECKGLERROR
7065 }
7066
7067 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7068 {
7069         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7070         {
7071                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7072                 if (r_timereport_active)
7073                         R_TimeReport("waterworld");
7074         }
7075
7076         // don't let sound skip if going slow
7077         if (r_refdef.scene.extraupdate)
7078                 S_ExtraUpdate ();
7079
7080         R_DrawModelsAddWaterPlanes();
7081         if (r_timereport_active)
7082                 R_TimeReport("watermodels");
7083
7084         if (r_fb.water.numwaterplanes)
7085         {
7086                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7087                 if (r_timereport_active)
7088                         R_TimeReport("waterscenes");
7089         }
7090 }
7091
7092 extern cvar_t cl_locs_show;
7093 static void R_DrawLocs(void);
7094 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7095 static void R_DrawModelDecals(void);
7096 extern cvar_t cl_decals_newsystem;
7097 extern qboolean r_shadow_usingdeferredprepass;
7098 extern int r_shadow_shadowmapatlas_modelshadows_size;
7099 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7100 {
7101         qboolean shadowmapping = false;
7102
7103         if (r_timereport_active)
7104                 R_TimeReport("beginscene");
7105
7106         r_refdef.stats[r_stat_renders]++;
7107
7108         R_UpdateFog();
7109
7110         // don't let sound skip if going slow
7111         if (r_refdef.scene.extraupdate)
7112                 S_ExtraUpdate ();
7113
7114         R_MeshQueue_BeginScene();
7115
7116         R_SkyStartFrame();
7117
7118         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);
7119
7120         if (r_timereport_active)
7121                 R_TimeReport("skystartframe");
7122
7123         if (cl.csqc_vidvars.drawworld)
7124         {
7125                 // don't let sound skip if going slow
7126                 if (r_refdef.scene.extraupdate)
7127                         S_ExtraUpdate ();
7128
7129                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7130                 {
7131                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7132                         if (r_timereport_active)
7133                                 R_TimeReport("worldsky");
7134                 }
7135
7136                 if (R_DrawBrushModelsSky() && r_timereport_active)
7137                         R_TimeReport("bmodelsky");
7138
7139                 if (skyrendermasked && skyrenderlater)
7140                 {
7141                         // we have to force off the water clipping plane while rendering sky
7142                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7143                         R_Sky();
7144                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7145                         if (r_timereport_active)
7146                                 R_TimeReport("sky");
7147                 }
7148         }
7149
7150         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7151         r_shadow_viewfbo = viewfbo;
7152         r_shadow_viewdepthtexture = viewdepthtexture;
7153         r_shadow_viewcolortexture = viewcolortexture;
7154         r_shadow_viewx = viewx;
7155         r_shadow_viewy = viewy;
7156         r_shadow_viewwidth = viewwidth;
7157         r_shadow_viewheight = viewheight;
7158
7159         R_Shadow_PrepareModelShadows();
7160         R_Shadow_PrepareLights();
7161         if (r_timereport_active)
7162                 R_TimeReport("preparelights");
7163
7164         // render all the shadowmaps that will be used for this view
7165         shadowmapping = R_Shadow_ShadowMappingEnabled();
7166         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7167         {
7168                 R_Shadow_DrawShadowMaps();
7169                 if (r_timereport_active)
7170                         R_TimeReport("shadowmaps");
7171         }
7172
7173         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7174         if (r_shadow_usingdeferredprepass)
7175                 R_Shadow_DrawPrepass();
7176
7177         // now we begin the forward pass of the view render
7178         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7179         {
7180                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7181                 if (r_timereport_active)
7182                         R_TimeReport("worlddepth");
7183         }
7184         if (r_depthfirst.integer >= 2)
7185         {
7186                 R_DrawModelsDepth();
7187                 if (r_timereport_active)
7188                         R_TimeReport("modeldepth");
7189         }
7190
7191         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7192         {
7193                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7194                 if (r_timereport_active)
7195                         R_TimeReport("world");
7196         }
7197
7198         // don't let sound skip if going slow
7199         if (r_refdef.scene.extraupdate)
7200                 S_ExtraUpdate ();
7201
7202         R_DrawModels();
7203         if (r_timereport_active)
7204                 R_TimeReport("models");
7205
7206         // don't let sound skip if going slow
7207         if (r_refdef.scene.extraupdate)
7208                 S_ExtraUpdate ();
7209
7210         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7211         {
7212                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7213                 R_Shadow_DrawModelShadows();
7214                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7215                 // don't let sound skip if going slow
7216                 if (r_refdef.scene.extraupdate)
7217                         S_ExtraUpdate ();
7218         }
7219
7220         if (!r_shadow_usingdeferredprepass)
7221         {
7222                 R_Shadow_DrawLights();
7223                 if (r_timereport_active)
7224                         R_TimeReport("rtlights");
7225         }
7226
7227         // don't let sound skip if going slow
7228         if (r_refdef.scene.extraupdate)
7229                 S_ExtraUpdate ();
7230
7231         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7232         {
7233                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7234                 R_Shadow_DrawModelShadows();
7235                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7236                 // don't let sound skip if going slow
7237                 if (r_refdef.scene.extraupdate)
7238                         S_ExtraUpdate ();
7239         }
7240
7241         if (cl.csqc_vidvars.drawworld)
7242         {
7243                 if (cl_decals_newsystem.integer)
7244                 {
7245                         R_DrawModelDecals();
7246                         if (r_timereport_active)
7247                                 R_TimeReport("modeldecals");
7248                 }
7249                 else
7250                 {
7251                         R_DrawDecals();
7252                         if (r_timereport_active)
7253                                 R_TimeReport("decals");
7254                 }
7255
7256                 R_DrawParticles();
7257                 if (r_timereport_active)
7258                         R_TimeReport("particles");
7259
7260                 R_DrawExplosions();
7261                 if (r_timereport_active)
7262                         R_TimeReport("explosions");
7263         }
7264
7265         if (r_refdef.view.showdebug)
7266         {
7267                 if (cl_locs_show.integer)
7268                 {
7269                         R_DrawLocs();
7270                         if (r_timereport_active)
7271                                 R_TimeReport("showlocs");
7272                 }
7273
7274                 if (r_drawportals.integer)
7275                 {
7276                         R_DrawPortals();
7277                         if (r_timereport_active)
7278                                 R_TimeReport("portals");
7279                 }
7280
7281                 if (r_showbboxes_client.value > 0)
7282                 {
7283                         R_DrawEntityBBoxes(CLVM_prog);
7284                         if (r_timereport_active)
7285                                 R_TimeReport("clbboxes");
7286                 }
7287                 if (r_showbboxes.value > 0)
7288                 {
7289                         R_DrawEntityBBoxes(SVVM_prog);
7290                         if (r_timereport_active)
7291                                 R_TimeReport("svbboxes");
7292                 }
7293         }
7294
7295         if (r_transparent.integer)
7296         {
7297                 R_MeshQueue_RenderTransparent();
7298                 if (r_timereport_active)
7299                         R_TimeReport("drawtrans");
7300         }
7301
7302         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))
7303         {
7304                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7305                 if (r_timereport_active)
7306                         R_TimeReport("worlddebug");
7307                 R_DrawModelsDebug();
7308                 if (r_timereport_active)
7309                         R_TimeReport("modeldebug");
7310         }
7311
7312         if (cl.csqc_vidvars.drawworld)
7313         {
7314                 R_Shadow_DrawCoronas();
7315                 if (r_timereport_active)
7316                         R_TimeReport("coronas");
7317         }
7318
7319 #if 0
7320         {
7321                 GL_DepthTest(false);
7322                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7323                 GL_Color(1, 1, 1, 1);
7324                 qglBegin(GL_POLYGON);
7325                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7326                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7327                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7328                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7329                 qglEnd();
7330                 qglBegin(GL_POLYGON);
7331                 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]);
7332                 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]);
7333                 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]);
7334                 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]);
7335                 qglEnd();
7336                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7337         }
7338 #endif
7339
7340         // don't let sound skip if going slow
7341         if (r_refdef.scene.extraupdate)
7342                 S_ExtraUpdate ();
7343 }
7344
7345 static const unsigned short bboxelements[36] =
7346 {
7347         5, 1, 3, 5, 3, 7,
7348         6, 2, 0, 6, 0, 4,
7349         7, 3, 2, 7, 2, 6,
7350         4, 0, 1, 4, 1, 5,
7351         4, 5, 7, 4, 7, 6,
7352         1, 0, 2, 1, 2, 3,
7353 };
7354
7355 #define BBOXEDGES 13
7356 static const float bboxedges[BBOXEDGES][6] = 
7357 {
7358         // whole box
7359         { 0, 0, 0, 1, 1, 1 },
7360         // bottom edges
7361         { 0, 0, 0, 0, 1, 0 },
7362         { 0, 0, 0, 1, 0, 0 },
7363         { 0, 1, 0, 1, 1, 0 },
7364         { 1, 0, 0, 1, 1, 0 },
7365         // top edges
7366         { 0, 0, 1, 0, 1, 1 },
7367         { 0, 0, 1, 1, 0, 1 },
7368         { 0, 1, 1, 1, 1, 1 },
7369         { 1, 0, 1, 1, 1, 1 },
7370         // vertical edges
7371         { 0, 0, 0, 0, 0, 1 },
7372         { 1, 0, 0, 1, 0, 1 },
7373         { 0, 1, 0, 0, 1, 1 },
7374         { 1, 1, 0, 1, 1, 1 },
7375 };
7376
7377 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7378 {
7379         int numvertices = BBOXEDGES * 8;
7380         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7381         int numtriangles = BBOXEDGES * 12;
7382         unsigned short elements[BBOXEDGES * 36];
7383         int i, edge;
7384         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7385
7386         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7387
7388         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7389         GL_DepthMask(false);
7390         GL_DepthRange(0, 1);
7391         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7392
7393         for (edge = 0; edge < BBOXEDGES; edge++)
7394         {
7395                 for (i = 0; i < 3; i++)
7396                 {
7397                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7398                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7399                 }
7400                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7401                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7402                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7403                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7404                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7405                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7406                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7407                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7408                 for (i = 0; i < 36; i++)
7409                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7410         }
7411         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7412         if (r_refdef.fogenabled)
7413         {
7414                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7415                 {
7416                         f1 = RSurf_FogVertex(v);
7417                         f2 = 1 - f1;
7418                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7419                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7420                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7421                 }
7422         }
7423         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7424         R_Mesh_ResetTextureState();
7425         R_SetupShader_Generic_NoTexture(false, false);
7426         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7427 }
7428
7429 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7430 {
7431         // hacky overloading of the parameters
7432         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7433         int i;
7434         float color[4];
7435         prvm_edict_t *edict;
7436
7437         GL_CullFace(GL_NONE);
7438         R_SetupShader_Generic_NoTexture(false, false);
7439
7440         for (i = 0;i < numsurfaces;i++)
7441         {
7442                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7443                 switch ((int)PRVM_serveredictfloat(edict, solid))
7444                 {
7445                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7446                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7447                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7448                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7449                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7450                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7451                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7452                 }
7453                 if (prog == CLVM_prog)
7454                         color[3] *= r_showbboxes_client.value;
7455                 else
7456                         color[3] *= r_showbboxes.value;
7457                 color[3] = bound(0, color[3], 1);
7458                 GL_DepthTest(!r_showdisabledepthtest.integer);
7459                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7460         }
7461 }
7462
7463 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7464 {
7465         int i;
7466         prvm_edict_t *edict;
7467         vec3_t center;
7468
7469         if (prog == NULL)
7470                 return;
7471
7472         for (i = 0; i < prog->num_edicts; i++)
7473         {
7474                 edict = PRVM_EDICT_NUM(i);
7475                 if (edict->priv.server->free)
7476                         continue;
7477                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7478                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7479                         continue;
7480                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7481                         continue;
7482                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7483                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7484         }
7485 }
7486
7487 static const int nomodelelement3i[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 unsigned short nomodelelement3s[24] =
7500 {
7501         5, 2, 0,
7502         5, 1, 2,
7503         5, 0, 3,
7504         5, 3, 1,
7505         0, 2, 4,
7506         2, 1, 4,
7507         3, 0, 4,
7508         1, 3, 4
7509 };
7510
7511 static const float nomodelvertex3f[6*3] =
7512 {
7513         -16,   0,   0,
7514          16,   0,   0,
7515           0, -16,   0,
7516           0,  16,   0,
7517           0,   0, -16,
7518           0,   0,  16
7519 };
7520
7521 static const float nomodelcolor4f[6*4] =
7522 {
7523         0.0f, 0.0f, 0.5f, 1.0f,
7524         0.0f, 0.0f, 0.5f, 1.0f,
7525         0.0f, 0.5f, 0.0f, 1.0f,
7526         0.0f, 0.5f, 0.0f, 1.0f,
7527         0.5f, 0.0f, 0.0f, 1.0f,
7528         0.5f, 0.0f, 0.0f, 1.0f
7529 };
7530
7531 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7532 {
7533         int i;
7534         float f1, f2, *c;
7535         float color4f[6*4];
7536
7537         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);
7538
7539         // this is only called once per entity so numsurfaces is always 1, and
7540         // surfacelist is always {0}, so this code does not handle batches
7541
7542         if (rsurface.ent_flags & RENDER_ADDITIVE)
7543         {
7544                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7545                 GL_DepthMask(false);
7546         }
7547         else if (ent->alpha < 1)
7548         {
7549                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7550                 GL_DepthMask(false);
7551         }
7552         else
7553         {
7554                 GL_BlendFunc(GL_ONE, GL_ZERO);
7555                 GL_DepthMask(true);
7556         }
7557         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7558         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7559         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7560         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7561         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7562         for (i = 0, c = color4f;i < 6;i++, c += 4)
7563         {
7564                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7565                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7566                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7567                 c[3] *= ent->alpha;
7568         }
7569         if (r_refdef.fogenabled)
7570         {
7571                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7572                 {
7573                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7574                         f2 = 1 - f1;
7575                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7576                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7577                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7578                 }
7579         }
7580 //      R_Mesh_ResetTextureState();
7581         R_SetupShader_Generic_NoTexture(false, false);
7582         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7583         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7584 }
7585
7586 void R_DrawNoModel(entity_render_t *ent)
7587 {
7588         vec3_t org;
7589         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7590         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7591                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7592         else
7593                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7594 }
7595
7596 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7597 {
7598         vec3_t right1, right2, diff, normal;
7599
7600         VectorSubtract (org2, org1, normal);
7601
7602         // calculate 'right' vector for start
7603         VectorSubtract (r_refdef.view.origin, org1, diff);
7604         CrossProduct (normal, diff, right1);
7605         VectorNormalize (right1);
7606
7607         // calculate 'right' vector for end
7608         VectorSubtract (r_refdef.view.origin, org2, diff);
7609         CrossProduct (normal, diff, right2);
7610         VectorNormalize (right2);
7611
7612         vert[ 0] = org1[0] + width * right1[0];
7613         vert[ 1] = org1[1] + width * right1[1];
7614         vert[ 2] = org1[2] + width * right1[2];
7615         vert[ 3] = org1[0] - width * right1[0];
7616         vert[ 4] = org1[1] - width * right1[1];
7617         vert[ 5] = org1[2] - width * right1[2];
7618         vert[ 6] = org2[0] - width * right2[0];
7619         vert[ 7] = org2[1] - width * right2[1];
7620         vert[ 8] = org2[2] - width * right2[2];
7621         vert[ 9] = org2[0] + width * right2[0];
7622         vert[10] = org2[1] + width * right2[1];
7623         vert[11] = org2[2] + width * right2[2];
7624 }
7625
7626 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)
7627 {
7628         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7629         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7630         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7631         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7632         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7633         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7634         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7635         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7636         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7637         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7638         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7639         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7640 }
7641
7642 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7643 {
7644         int i;
7645         float *vertex3f;
7646         float v[3];
7647         VectorSet(v, x, y, z);
7648         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7649                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7650                         break;
7651         if (i == mesh->numvertices)
7652         {
7653                 if (mesh->numvertices < mesh->maxvertices)
7654                 {
7655                         VectorCopy(v, vertex3f);
7656                         mesh->numvertices++;
7657                 }
7658                 return mesh->numvertices;
7659         }
7660         else
7661                 return i;
7662 }
7663
7664 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7665 {
7666         int i;
7667         int *e, element[3];
7668         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7669         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7670         e = mesh->element3i + mesh->numtriangles * 3;
7671         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7672         {
7673                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7674                 if (mesh->numtriangles < mesh->maxtriangles)
7675                 {
7676                         *e++ = element[0];
7677                         *e++ = element[1];
7678                         *e++ = element[2];
7679                         mesh->numtriangles++;
7680                 }
7681                 element[1] = element[2];
7682         }
7683 }
7684
7685 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7686 {
7687         int i;
7688         int *e, element[3];
7689         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7690         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7691         e = mesh->element3i + mesh->numtriangles * 3;
7692         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7693         {
7694                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7695                 if (mesh->numtriangles < mesh->maxtriangles)
7696                 {
7697                         *e++ = element[0];
7698                         *e++ = element[1];
7699                         *e++ = element[2];
7700                         mesh->numtriangles++;
7701                 }
7702                 element[1] = element[2];
7703         }
7704 }
7705
7706 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7707 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7708 {
7709         int planenum, planenum2;
7710         int w;
7711         int tempnumpoints;
7712         mplane_t *plane, *plane2;
7713         double maxdist;
7714         double temppoints[2][256*3];
7715         // figure out how large a bounding box we need to properly compute this brush
7716         maxdist = 0;
7717         for (w = 0;w < numplanes;w++)
7718                 maxdist = max(maxdist, fabs(planes[w].dist));
7719         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7720         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7721         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7722         {
7723                 w = 0;
7724                 tempnumpoints = 4;
7725                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7726                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7727                 {
7728                         if (planenum2 == planenum)
7729                                 continue;
7730                         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);
7731                         w = !w;
7732                 }
7733                 if (tempnumpoints < 3)
7734                         continue;
7735                 // generate elements forming a triangle fan for this polygon
7736                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7737         }
7738 }
7739
7740 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)
7741 {
7742         texturelayer_t *layer;
7743         layer = t->currentlayers + t->currentnumlayers++;
7744         layer->type = type;
7745         layer->depthmask = depthmask;
7746         layer->blendfunc1 = blendfunc1;
7747         layer->blendfunc2 = blendfunc2;
7748         layer->texture = texture;
7749         layer->texmatrix = *matrix;
7750         layer->color[0] = r;
7751         layer->color[1] = g;
7752         layer->color[2] = b;
7753         layer->color[3] = a;
7754 }
7755
7756 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7757 {
7758         if(parms[0] == 0 && parms[1] == 0)
7759                 return false;
7760         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7761                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7762                         return false;
7763         return true;
7764 }
7765
7766 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7767 {
7768         double index, f;
7769         index = parms[2] + rsurface.shadertime * parms[3];
7770         index -= floor(index);
7771         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7772         {
7773         default:
7774         case Q3WAVEFUNC_NONE:
7775         case Q3WAVEFUNC_NOISE:
7776         case Q3WAVEFUNC_COUNT:
7777                 f = 0;
7778                 break;
7779         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7780         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7781         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7782         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7783         case Q3WAVEFUNC_TRIANGLE:
7784                 index *= 4;
7785                 f = index - floor(index);
7786                 if (index < 1)
7787                 {
7788                         // f = f;
7789                 }
7790                 else if (index < 2)
7791                         f = 1 - f;
7792                 else if (index < 3)
7793                         f = -f;
7794                 else
7795                         f = -(1 - f);
7796                 break;
7797         }
7798         f = parms[0] + parms[1] * f;
7799         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7800                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7801         return (float) f;
7802 }
7803
7804 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7805 {
7806         int w, h, idx;
7807         float shadertime;
7808         float f;
7809         float offsetd[2];
7810         float tcmat[12];
7811         matrix4x4_t matrix, temp;
7812         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7813         // it's better to have one huge fixup every 9 hours than gradual
7814         // degradation over time which looks consistently bad after many hours.
7815         //
7816         // tcmod scroll in particular suffers from this degradation which can't be
7817         // effectively worked around even with floor() tricks because we don't
7818         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7819         // a workaround involving floor() would be incorrect anyway...
7820         shadertime = rsurface.shadertime;
7821         if (shadertime >= 32768.0f)
7822                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7823         switch(tcmod->tcmod)
7824         {
7825                 case Q3TCMOD_COUNT:
7826                 case Q3TCMOD_NONE:
7827                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7828                                 matrix = r_waterscrollmatrix;
7829                         else
7830                                 matrix = identitymatrix;
7831                         break;
7832                 case Q3TCMOD_ENTITYTRANSLATE:
7833                         // this is used in Q3 to allow the gamecode to control texcoord
7834                         // scrolling on the entity, which is not supported in darkplaces yet.
7835                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7836                         break;
7837                 case Q3TCMOD_ROTATE:
7838                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7839                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7840                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7841                         break;
7842                 case Q3TCMOD_SCALE:
7843                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7844                         break;
7845                 case Q3TCMOD_SCROLL:
7846                         // this particular tcmod is a "bug for bug" compatible one with regards to
7847                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7848                         // specifically did the wrapping and so we must mimic that...
7849                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7850                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7851                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7852                         break;
7853                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7854                         w = (int) tcmod->parms[0];
7855                         h = (int) tcmod->parms[1];
7856                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7857                         f = f - floor(f);
7858                         idx = (int) floor(f * w * h);
7859                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7860                         break;
7861                 case Q3TCMOD_STRETCH:
7862                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7863                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7864                         break;
7865                 case Q3TCMOD_TRANSFORM:
7866                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7867                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7868                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7869                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7870                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7871                         break;
7872                 case Q3TCMOD_TURBULENT:
7873                         // this is handled in the RSurf_PrepareVertices function
7874                         matrix = identitymatrix;
7875                         break;
7876         }
7877         temp = *texmatrix;
7878         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7879 }
7880
7881 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7882 {
7883         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7884         char name[MAX_QPATH];
7885         skinframe_t *skinframe;
7886         unsigned char pixels[296*194];
7887         strlcpy(cache->name, skinname, sizeof(cache->name));
7888         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7889         if (developer_loading.integer)
7890                 Con_Printf("loading %s\n", name);
7891         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7892         if (!skinframe || !skinframe->base)
7893         {
7894                 unsigned char *f;
7895                 fs_offset_t filesize;
7896                 skinframe = NULL;
7897                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7898                 if (f)
7899                 {
7900                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7901                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7902                         Mem_Free(f);
7903                 }
7904         }
7905         cache->skinframe = skinframe;
7906 }
7907
7908 texture_t *R_GetCurrentTexture(texture_t *t)
7909 {
7910         int i, q;
7911         const entity_render_t *ent = rsurface.entity;
7912         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7913         q3shaderinfo_layer_tcmod_t *tcmod;
7914         float specularscale = 0.0f;
7915
7916         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7917                 return t->currentframe;
7918         t->update_lastrenderframe = r_textureframe;
7919         t->update_lastrenderentity = (void *)ent;
7920
7921         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7922                 t->camera_entity = ent->entitynumber;
7923         else
7924                 t->camera_entity = 0;
7925
7926         // switch to an alternate material if this is a q1bsp animated material
7927         {
7928                 texture_t *texture = t;
7929                 int s = rsurface.ent_skinnum;
7930                 if ((unsigned int)s >= (unsigned int)model->numskins)
7931                         s = 0;
7932                 if (model->skinscenes)
7933                 {
7934                         if (model->skinscenes[s].framecount > 1)
7935                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7936                         else
7937                                 s = model->skinscenes[s].firstframe;
7938                 }
7939                 if (s > 0)
7940                         t = t + s * model->num_surfaces;
7941                 if (t->animated)
7942                 {
7943                         // use an alternate animation if the entity's frame is not 0,
7944                         // and only if the texture has an alternate animation
7945                         if (t->animated == 2) // q2bsp
7946                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7947                         else if (rsurface.ent_alttextures && t->anim_total[1])
7948                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7949                         else
7950                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7951                 }
7952                 texture->currentframe = t;
7953         }
7954
7955         // update currentskinframe to be a qw skin or animation frame
7956         if (rsurface.ent_qwskin >= 0)
7957         {
7958                 i = rsurface.ent_qwskin;
7959                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7960                 {
7961                         r_qwskincache_size = cl.maxclients;
7962                         if (r_qwskincache)
7963                                 Mem_Free(r_qwskincache);
7964                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7965                 }
7966                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7967                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7968                 t->currentskinframe = r_qwskincache[i].skinframe;
7969                 if (t->materialshaderpass && t->currentskinframe == NULL)
7970                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7971         }
7972         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7973                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7974         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7975                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7976
7977         t->currentmaterialflags = t->basematerialflags;
7978         t->currentalpha = rsurface.entity->alpha * t->basealpha;
7979         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7980                 t->currentalpha *= r_wateralpha.value;
7981         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7982                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7983         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7984                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7985
7986         // decide on which type of lighting to use for this surface
7987         if (rsurface.entity->render_modellight_forced)
7988                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7989         if (rsurface.entity->render_rtlight_disabled)
7990                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
7991         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
7992         {
7993                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
7994                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
7995                 for (q = 0; q < 3; q++)
7996                 {
7997                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
7998                         t->render_modellight_lightdir[q] = q == 2;
7999                         t->render_modellight_ambient[q] = 1;
8000                         t->render_modellight_diffuse[q] = 0;
8001                         t->render_modellight_specular[q] = 0;
8002                         t->render_lightmap_ambient[q] = 0;
8003                         t->render_lightmap_diffuse[q] = 0;
8004                         t->render_lightmap_specular[q] = 0;
8005                         t->render_rtlight_diffuse[q] = 0;
8006                         t->render_rtlight_specular[q] = 0;
8007                 }
8008         }
8009         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8010         {
8011                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8012                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8013                 for (q = 0; q < 3; q++)
8014                 {
8015                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8016                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8017                         t->render_modellight_lightdir[q] = q == 2;
8018                         t->render_modellight_diffuse[q] = 0;
8019                         t->render_modellight_specular[q] = 0;
8020                         t->render_lightmap_ambient[q] = 0;
8021                         t->render_lightmap_diffuse[q] = 0;
8022                         t->render_lightmap_specular[q] = 0;
8023                         t->render_rtlight_diffuse[q] = 0;
8024                         t->render_rtlight_specular[q] = 0;
8025                 }
8026         }
8027         else if (FAKELIGHT_ENABLED)
8028         {
8029                 // no modellight if using fakelight for the map
8030                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8031                 for (q = 0; q < 3; q++)
8032                 {
8033                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8034                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8035                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8036                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8037                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8038                         t->render_lightmap_ambient[q] = 0;
8039                         t->render_lightmap_diffuse[q] = 0;
8040                         t->render_lightmap_specular[q] = 0;
8041                         t->render_rtlight_diffuse[q] = 0;
8042                         t->render_rtlight_specular[q] = 0;
8043                 }
8044         }
8045         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8046         {
8047                 // ambient + single direction light (modellight)
8048                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8049                 for (q = 0; q < 3; q++)
8050                 {
8051                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8052                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8053                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8054                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8055                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8056                         t->render_lightmap_ambient[q] = 0;
8057                         t->render_lightmap_diffuse[q] = 0;
8058                         t->render_lightmap_specular[q] = 0;
8059                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8060                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8061                 }
8062         }
8063         else
8064         {
8065                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8066                 for (q = 0; q < 3; q++)
8067                 {
8068                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8069                         t->render_modellight_lightdir[q] = q == 2;
8070                         t->render_modellight_ambient[q] = 0;
8071                         t->render_modellight_diffuse[q] = 0;
8072                         t->render_modellight_specular[q] = 0;
8073                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8074                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8075                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8076                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8077                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8078                 }
8079         }
8080
8081         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8082         {
8083                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8084                 // attribute, we punt it to the lightmap path and hope for the best,
8085                 // but lighting doesn't work.
8086                 //
8087                 // FIXME: this is fine for effects but CSQC polygons should be subject
8088                 // to lighting.
8089                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8090                 for (q = 0; q < 3; q++)
8091                 {
8092                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8093                         t->render_modellight_lightdir[q] = q == 2;
8094                         t->render_modellight_ambient[q] = 0;
8095                         t->render_modellight_diffuse[q] = 0;
8096                         t->render_modellight_specular[q] = 0;
8097                         t->render_lightmap_ambient[q] = 0;
8098                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8099                         t->render_lightmap_specular[q] = 0;
8100                         t->render_rtlight_diffuse[q] = 0;
8101                         t->render_rtlight_specular[q] = 0;
8102                 }
8103         }
8104
8105         for (q = 0; q < 3; q++)
8106         {
8107                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8108                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8109         }
8110
8111         if (rsurface.ent_flags & RENDER_ADDITIVE)
8112                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8113         else if (t->currentalpha < 1)
8114                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8115         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8116         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8117                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8118         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8119                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8120         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8121                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8122         if (t->backgroundshaderpass)
8123                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8124         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8125         {
8126                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8127                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8128         }
8129         else
8130                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8131         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8132         {
8133                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8134                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8135         }
8136         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8137                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8138
8139         // there is no tcmod
8140         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8141         {
8142                 t->currenttexmatrix = r_waterscrollmatrix;
8143                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8144         }
8145         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8146         {
8147                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8148                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8149         }
8150
8151         if (t->materialshaderpass)
8152                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8153                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8154
8155         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8156         if (t->currentskinframe->qpixels)
8157                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8158         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8159         if (!t->basetexture)
8160                 t->basetexture = r_texture_notexture;
8161         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8162         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8163         t->nmaptexture = t->currentskinframe->nmap;
8164         if (!t->nmaptexture)
8165                 t->nmaptexture = r_texture_blanknormalmap;
8166         t->glosstexture = r_texture_black;
8167         t->glowtexture = t->currentskinframe->glow;
8168         t->fogtexture = t->currentskinframe->fog;
8169         t->reflectmasktexture = t->currentskinframe->reflect;
8170         if (t->backgroundshaderpass)
8171         {
8172                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8173                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8174                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8175                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8176                 t->backgroundglosstexture = r_texture_black;
8177                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8178                 if (!t->backgroundnmaptexture)
8179                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8180                 // make sure that if glow is going to be used, both textures are not NULL
8181                 if (!t->backgroundglowtexture && t->glowtexture)
8182                         t->backgroundglowtexture = r_texture_black;
8183                 if (!t->glowtexture && t->backgroundglowtexture)
8184                         t->glowtexture = r_texture_black;
8185         }
8186         else
8187         {
8188                 t->backgroundbasetexture = r_texture_white;
8189                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8190                 t->backgroundglosstexture = r_texture_black;
8191                 t->backgroundglowtexture = NULL;
8192         }
8193         t->specularpower = r_shadow_glossexponent.value;
8194         // TODO: store reference values for these in the texture?
8195         if (r_shadow_gloss.integer > 0)
8196         {
8197                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8198                 {
8199                         if (r_shadow_glossintensity.value > 0)
8200                         {
8201                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8202                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8203                                 specularscale = r_shadow_glossintensity.value;
8204                         }
8205                 }
8206                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8207                 {
8208                         t->glosstexture = r_texture_white;
8209                         t->backgroundglosstexture = r_texture_white;
8210                         specularscale = r_shadow_gloss2intensity.value;
8211                         t->specularpower = r_shadow_gloss2exponent.value;
8212                 }
8213         }
8214         specularscale *= t->specularscalemod;
8215         t->specularpower *= t->specularpowermod;
8216
8217         // lightmaps mode looks bad with dlights using actual texturing, so turn
8218         // off the colormap and glossmap, but leave the normalmap on as it still
8219         // accurately represents the shading involved
8220         if (gl_lightmaps.integer)
8221         {
8222                 t->basetexture = r_texture_grey128;
8223                 t->pantstexture = r_texture_black;
8224                 t->shirttexture = r_texture_black;
8225                 if (gl_lightmaps.integer < 2)
8226                         t->nmaptexture = r_texture_blanknormalmap;
8227                 t->glosstexture = r_texture_black;
8228                 t->glowtexture = NULL;
8229                 t->fogtexture = NULL;
8230                 t->reflectmasktexture = NULL;
8231                 t->backgroundbasetexture = NULL;
8232                 if (gl_lightmaps.integer < 2)
8233                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8234                 t->backgroundglosstexture = r_texture_black;
8235                 t->backgroundglowtexture = NULL;
8236                 specularscale = 0;
8237                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8238         }
8239
8240         if (specularscale != 1.0f)
8241         {
8242                 for (q = 0; q < 3; q++)
8243                 {
8244                         t->render_modellight_specular[q] *= specularscale;
8245                         t->render_lightmap_specular[q] *= specularscale;
8246                         t->render_rtlight_specular[q] *= specularscale;
8247                 }
8248         }
8249
8250         t->currentnumlayers = 0;
8251         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8252         {
8253                 int blendfunc1, blendfunc2;
8254                 qboolean depthmask;
8255                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8256                 {
8257                         blendfunc1 = GL_SRC_ALPHA;
8258                         blendfunc2 = GL_ONE;
8259                 }
8260                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8261                 {
8262                         blendfunc1 = GL_SRC_ALPHA;
8263                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8264                 }
8265                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8266                 {
8267                         blendfunc1 = t->customblendfunc[0];
8268                         blendfunc2 = t->customblendfunc[1];
8269                 }
8270                 else
8271                 {
8272                         blendfunc1 = GL_ONE;
8273                         blendfunc2 = GL_ZERO;
8274                 }
8275                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8276                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8277                 {
8278                         // basic lit geometry
8279                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
8280                         // add pants/shirt if needed
8281                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8282                                 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);
8283                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8284                                 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);
8285                 }
8286                 else
8287                 {
8288                         // basic lit geometry
8289                         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);
8290                         // add pants/shirt if needed
8291                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8292                                 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);
8293                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8294                                 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);
8295                         // now add ambient passes if needed
8296                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8297                         {
8298                                 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);
8299                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8300                                         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);
8301                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8302                                         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);
8303                         }
8304                 }
8305                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8306                         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);
8307                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8308                 {
8309                         // if this is opaque use alpha blend which will darken the earlier
8310                         // passes cheaply.
8311                         //
8312                         // if this is an alpha blended material, all the earlier passes
8313                         // were darkened by fog already, so we only need to add the fog
8314                         // color ontop through the fog mask texture
8315                         //
8316                         // if this is an additive blended material, all the earlier passes
8317                         // were darkened by fog already, and we should not add fog color
8318                         // (because the background was not darkened, there is no fog color
8319                         // that was lost behind it).
8320                         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);
8321                 }
8322         }
8323
8324         return t;
8325 }
8326
8327 rsurfacestate_t rsurface;
8328
8329 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8330 {
8331         dp_model_t *model = ent->model;
8332         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8333         //      return;
8334         rsurface.entity = (entity_render_t *)ent;
8335         rsurface.skeleton = ent->skeleton;
8336         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8337         rsurface.ent_skinnum = ent->skinnum;
8338         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;
8339         rsurface.ent_flags = ent->flags;
8340         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8341                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8342         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8343         rsurface.matrix = ent->matrix;
8344         rsurface.inversematrix = ent->inversematrix;
8345         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8346         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8347         R_EntityMatrix(&rsurface.matrix);
8348         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8349         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8350         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8351         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8352         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8353         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8354         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8355         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8356         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8357         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8358         if (ent->model->brush.submodel && !prepass)
8359         {
8360                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8361                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8362         }
8363         // if the animcache code decided it should use the shader path, skip the deform step
8364         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8365         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8366         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8367         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8368         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8369         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8370         {
8371                 if (ent->animcache_vertex3f)
8372                 {
8373                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8374                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8375                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8376                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8377                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8378                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8379                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8380                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8381                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8382                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8383                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8384                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8385                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8386                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8387                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8388                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8389                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8390                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8391                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8392                 }
8393                 else if (wanttangents)
8394                 {
8395                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8396                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8397                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8398                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8399                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8400                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8401                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8402                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8403                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8404                         rsurface.modelvertexmesh = NULL;
8405                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8406                         rsurface.modelvertexmesh_bufferoffset = 0;
8407                         rsurface.modelvertex3f_vertexbuffer = NULL;
8408                         rsurface.modelvertex3f_bufferoffset = 0;
8409                         rsurface.modelvertex3f_vertexbuffer = 0;
8410                         rsurface.modelvertex3f_bufferoffset = 0;
8411                         rsurface.modelsvector3f_vertexbuffer = 0;
8412                         rsurface.modelsvector3f_bufferoffset = 0;
8413                         rsurface.modeltvector3f_vertexbuffer = 0;
8414                         rsurface.modeltvector3f_bufferoffset = 0;
8415                         rsurface.modelnormal3f_vertexbuffer = 0;
8416                         rsurface.modelnormal3f_bufferoffset = 0;
8417                 }
8418                 else if (wantnormals)
8419                 {
8420                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8421                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8422                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8423                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8424                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8425                         rsurface.modelsvector3f = NULL;
8426                         rsurface.modeltvector3f = NULL;
8427                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8428                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8429                         rsurface.modelvertexmesh = NULL;
8430                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8431                         rsurface.modelvertexmesh_bufferoffset = 0;
8432                         rsurface.modelvertex3f_vertexbuffer = NULL;
8433                         rsurface.modelvertex3f_bufferoffset = 0;
8434                         rsurface.modelvertex3f_vertexbuffer = 0;
8435                         rsurface.modelvertex3f_bufferoffset = 0;
8436                         rsurface.modelsvector3f_vertexbuffer = 0;
8437                         rsurface.modelsvector3f_bufferoffset = 0;
8438                         rsurface.modeltvector3f_vertexbuffer = 0;
8439                         rsurface.modeltvector3f_bufferoffset = 0;
8440                         rsurface.modelnormal3f_vertexbuffer = 0;
8441                         rsurface.modelnormal3f_bufferoffset = 0;
8442                 }
8443                 else
8444                 {
8445                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8446                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8447                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8448                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8449                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8450                         rsurface.modelsvector3f = NULL;
8451                         rsurface.modeltvector3f = NULL;
8452                         rsurface.modelnormal3f = NULL;
8453                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8454                         rsurface.modelvertexmesh = NULL;
8455                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8456                         rsurface.modelvertexmesh_bufferoffset = 0;
8457                         rsurface.modelvertex3f_vertexbuffer = NULL;
8458                         rsurface.modelvertex3f_bufferoffset = 0;
8459                         rsurface.modelvertex3f_vertexbuffer = 0;
8460                         rsurface.modelvertex3f_bufferoffset = 0;
8461                         rsurface.modelsvector3f_vertexbuffer = 0;
8462                         rsurface.modelsvector3f_bufferoffset = 0;
8463                         rsurface.modeltvector3f_vertexbuffer = 0;
8464                         rsurface.modeltvector3f_bufferoffset = 0;
8465                         rsurface.modelnormal3f_vertexbuffer = 0;
8466                         rsurface.modelnormal3f_bufferoffset = 0;
8467                 }
8468                 rsurface.modelgeneratedvertex = true;
8469         }
8470         else
8471         {
8472                 if (rsurface.entityskeletaltransform3x4)
8473                 {
8474                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8475                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8476                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8477                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8478                 }
8479                 else
8480                 {
8481                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8482                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8483                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8484                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8485                 }
8486                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8487                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8489                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8490                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8492                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8493                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8495                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8496                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8498                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8499                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8501                 rsurface.modelgeneratedvertex = false;
8502         }
8503         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8504         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8506         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8507         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8508         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8509         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8510         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8511         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8512         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8513         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8514         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8515         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8516         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8517         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8518         rsurface.modelelement3i = model->surfmesh.data_element3i;
8519         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8520         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8521         rsurface.modelelement3s = model->surfmesh.data_element3s;
8522         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8523         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8524         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8525         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8526         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8527         rsurface.modelsurfaces = model->data_surfaces;
8528         rsurface.batchgeneratedvertex = false;
8529         rsurface.batchfirstvertex = 0;
8530         rsurface.batchnumvertices = 0;
8531         rsurface.batchfirsttriangle = 0;
8532         rsurface.batchnumtriangles = 0;
8533         rsurface.batchvertex3f  = NULL;
8534         rsurface.batchvertex3f_vertexbuffer = NULL;
8535         rsurface.batchvertex3f_bufferoffset = 0;
8536         rsurface.batchsvector3f = NULL;
8537         rsurface.batchsvector3f_vertexbuffer = NULL;
8538         rsurface.batchsvector3f_bufferoffset = 0;
8539         rsurface.batchtvector3f = NULL;
8540         rsurface.batchtvector3f_vertexbuffer = NULL;
8541         rsurface.batchtvector3f_bufferoffset = 0;
8542         rsurface.batchnormal3f  = NULL;
8543         rsurface.batchnormal3f_vertexbuffer = NULL;
8544         rsurface.batchnormal3f_bufferoffset = 0;
8545         rsurface.batchlightmapcolor4f = NULL;
8546         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8547         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8548         rsurface.batchtexcoordtexture2f = NULL;
8549         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8550         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8551         rsurface.batchtexcoordlightmap2f = NULL;
8552         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8553         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8554         rsurface.batchskeletalindex4ub = NULL;
8555         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8556         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8557         rsurface.batchskeletalweight4ub = NULL;
8558         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8559         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8560         rsurface.batchvertexmesh = NULL;
8561         rsurface.batchvertexmesh_vertexbuffer = NULL;
8562         rsurface.batchvertexmesh_bufferoffset = 0;
8563         rsurface.batchelement3i = NULL;
8564         rsurface.batchelement3i_indexbuffer = NULL;
8565         rsurface.batchelement3i_bufferoffset = 0;
8566         rsurface.batchelement3s = NULL;
8567         rsurface.batchelement3s_indexbuffer = NULL;
8568         rsurface.batchelement3s_bufferoffset = 0;
8569         rsurface.passcolor4f = NULL;
8570         rsurface.passcolor4f_vertexbuffer = NULL;
8571         rsurface.passcolor4f_bufferoffset = 0;
8572         rsurface.forcecurrenttextureupdate = false;
8573 }
8574
8575 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)
8576 {
8577         rsurface.entity = r_refdef.scene.worldentity;
8578         rsurface.skeleton = NULL;
8579         rsurface.ent_skinnum = 0;
8580         rsurface.ent_qwskin = -1;
8581         rsurface.ent_flags = entflags;
8582         rsurface.shadertime = r_refdef.scene.time - shadertime;
8583         rsurface.modelnumvertices = numvertices;
8584         rsurface.modelnumtriangles = numtriangles;
8585         rsurface.matrix = *matrix;
8586         rsurface.inversematrix = *inversematrix;
8587         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8588         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8589         R_EntityMatrix(&rsurface.matrix);
8590         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8591         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8592         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8593         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8594         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8595         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8596         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8597         rsurface.frameblend[0].lerp = 1;
8598         rsurface.ent_alttextures = false;
8599         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8600         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8601         rsurface.entityskeletaltransform3x4 = NULL;
8602         rsurface.entityskeletaltransform3x4buffer = NULL;
8603         rsurface.entityskeletaltransform3x4offset = 0;
8604         rsurface.entityskeletaltransform3x4size = 0;
8605         rsurface.entityskeletalnumtransforms = 0;
8606         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8607         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8608         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8609         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8610         if (wanttangents)
8611         {
8612                 rsurface.modelvertex3f = (float *)vertex3f;
8613                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8614                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8615                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8616         }
8617         else if (wantnormals)
8618         {
8619                 rsurface.modelvertex3f = (float *)vertex3f;
8620                 rsurface.modelsvector3f = NULL;
8621                 rsurface.modeltvector3f = NULL;
8622                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8623         }
8624         else
8625         {
8626                 rsurface.modelvertex3f = (float *)vertex3f;
8627                 rsurface.modelsvector3f = NULL;
8628                 rsurface.modeltvector3f = NULL;
8629                 rsurface.modelnormal3f = NULL;
8630         }
8631         rsurface.modelvertexmesh = NULL;
8632         rsurface.modelvertexmesh_vertexbuffer = NULL;
8633         rsurface.modelvertexmesh_bufferoffset = 0;
8634         rsurface.modelvertex3f_vertexbuffer = 0;
8635         rsurface.modelvertex3f_bufferoffset = 0;
8636         rsurface.modelsvector3f_vertexbuffer = 0;
8637         rsurface.modelsvector3f_bufferoffset = 0;
8638         rsurface.modeltvector3f_vertexbuffer = 0;
8639         rsurface.modeltvector3f_bufferoffset = 0;
8640         rsurface.modelnormal3f_vertexbuffer = 0;
8641         rsurface.modelnormal3f_bufferoffset = 0;
8642         rsurface.modelgeneratedvertex = true;
8643         rsurface.modellightmapcolor4f  = (float *)color4f;
8644         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8645         rsurface.modellightmapcolor4f_bufferoffset = 0;
8646         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8647         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8648         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8649         rsurface.modeltexcoordlightmap2f  = NULL;
8650         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8651         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8652         rsurface.modelskeletalindex4ub = NULL;
8653         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8654         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8655         rsurface.modelskeletalweight4ub = NULL;
8656         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8657         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8658         rsurface.modelelement3i = (int *)element3i;
8659         rsurface.modelelement3i_indexbuffer = NULL;
8660         rsurface.modelelement3i_bufferoffset = 0;
8661         rsurface.modelelement3s = (unsigned short *)element3s;
8662         rsurface.modelelement3s_indexbuffer = NULL;
8663         rsurface.modelelement3s_bufferoffset = 0;
8664         rsurface.modellightmapoffsets = NULL;
8665         rsurface.modelsurfaces = NULL;
8666         rsurface.batchgeneratedvertex = false;
8667         rsurface.batchfirstvertex = 0;
8668         rsurface.batchnumvertices = 0;
8669         rsurface.batchfirsttriangle = 0;
8670         rsurface.batchnumtriangles = 0;
8671         rsurface.batchvertex3f  = NULL;
8672         rsurface.batchvertex3f_vertexbuffer = NULL;
8673         rsurface.batchvertex3f_bufferoffset = 0;
8674         rsurface.batchsvector3f = NULL;
8675         rsurface.batchsvector3f_vertexbuffer = NULL;
8676         rsurface.batchsvector3f_bufferoffset = 0;
8677         rsurface.batchtvector3f = NULL;
8678         rsurface.batchtvector3f_vertexbuffer = NULL;
8679         rsurface.batchtvector3f_bufferoffset = 0;
8680         rsurface.batchnormal3f  = NULL;
8681         rsurface.batchnormal3f_vertexbuffer = NULL;
8682         rsurface.batchnormal3f_bufferoffset = 0;
8683         rsurface.batchlightmapcolor4f = NULL;
8684         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8685         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8686         rsurface.batchtexcoordtexture2f = NULL;
8687         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8688         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8689         rsurface.batchtexcoordlightmap2f = NULL;
8690         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8691         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8692         rsurface.batchskeletalindex4ub = NULL;
8693         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8694         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8695         rsurface.batchskeletalweight4ub = NULL;
8696         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8697         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8698         rsurface.batchvertexmesh = NULL;
8699         rsurface.batchvertexmesh_vertexbuffer = NULL;
8700         rsurface.batchvertexmesh_bufferoffset = 0;
8701         rsurface.batchelement3i = NULL;
8702         rsurface.batchelement3i_indexbuffer = NULL;
8703         rsurface.batchelement3i_bufferoffset = 0;
8704         rsurface.batchelement3s = NULL;
8705         rsurface.batchelement3s_indexbuffer = NULL;
8706         rsurface.batchelement3s_bufferoffset = 0;
8707         rsurface.passcolor4f = NULL;
8708         rsurface.passcolor4f_vertexbuffer = NULL;
8709         rsurface.passcolor4f_bufferoffset = 0;
8710         rsurface.forcecurrenttextureupdate = true;
8711
8712         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8713         {
8714                 if ((wantnormals || wanttangents) && !normal3f)
8715                 {
8716                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8717                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8718                 }
8719                 if (wanttangents && !svector3f)
8720                 {
8721                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8722                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8723                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8724                 }
8725         }
8726 }
8727
8728 float RSurf_FogPoint(const float *v)
8729 {
8730         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8731         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8732         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8733         float FogHeightFade = r_refdef.fogheightfade;
8734         float fogfrac;
8735         unsigned int fogmasktableindex;
8736         if (r_refdef.fogplaneviewabove)
8737                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8738         else
8739                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8740         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8741         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8742 }
8743
8744 float RSurf_FogVertex(const float *v)
8745 {
8746         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8747         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8748         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8749         float FogHeightFade = rsurface.fogheightfade;
8750         float fogfrac;
8751         unsigned int fogmasktableindex;
8752         if (r_refdef.fogplaneviewabove)
8753                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8754         else
8755                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8756         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8757         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8758 }
8759
8760 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8761 {
8762         int i;
8763         for (i = 0;i < numelements;i++)
8764                 outelement3i[i] = inelement3i[i] + adjust;
8765 }
8766
8767 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8768 extern cvar_t gl_vbo;
8769 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8770 {
8771         int deformindex;
8772         int firsttriangle;
8773         int numtriangles;
8774         int firstvertex;
8775         int endvertex;
8776         int numvertices;
8777         int surfacefirsttriangle;
8778         int surfacenumtriangles;
8779         int surfacefirstvertex;
8780         int surfaceendvertex;
8781         int surfacenumvertices;
8782         int batchnumsurfaces = texturenumsurfaces;
8783         int batchnumvertices;
8784         int batchnumtriangles;
8785         int needsupdate;
8786         int i, j;
8787         qboolean gaps;
8788         qboolean dynamicvertex;
8789         float amplitude;
8790         float animpos;
8791         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8792         float waveparms[4];
8793         unsigned char *ub;
8794         q3shaderinfo_deform_t *deform;
8795         const msurface_t *surface, *firstsurface;
8796         r_vertexmesh_t *vertexmesh;
8797         if (!texturenumsurfaces)
8798                 return;
8799         // find vertex range of this surface batch
8800         gaps = false;
8801         firstsurface = texturesurfacelist[0];
8802         firsttriangle = firstsurface->num_firsttriangle;
8803         batchnumvertices = 0;
8804         batchnumtriangles = 0;
8805         firstvertex = endvertex = firstsurface->num_firstvertex;
8806         for (i = 0;i < texturenumsurfaces;i++)
8807         {
8808                 surface = texturesurfacelist[i];
8809                 if (surface != firstsurface + i)
8810                         gaps = true;
8811                 surfacefirstvertex = surface->num_firstvertex;
8812                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8813                 surfacenumvertices = surface->num_vertices;
8814                 surfacenumtriangles = surface->num_triangles;
8815                 if (firstvertex > surfacefirstvertex)
8816                         firstvertex = surfacefirstvertex;
8817                 if (endvertex < surfaceendvertex)
8818                         endvertex = surfaceendvertex;
8819                 batchnumvertices += surfacenumvertices;
8820                 batchnumtriangles += surfacenumtriangles;
8821         }
8822
8823         r_refdef.stats[r_stat_batch_batches]++;
8824         if (gaps)
8825                 r_refdef.stats[r_stat_batch_withgaps]++;
8826         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8827         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8828         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8829
8830         // we now know the vertex range used, and if there are any gaps in it
8831         rsurface.batchfirstvertex = firstvertex;
8832         rsurface.batchnumvertices = endvertex - firstvertex;
8833         rsurface.batchfirsttriangle = firsttriangle;
8834         rsurface.batchnumtriangles = batchnumtriangles;
8835
8836         // this variable holds flags for which properties have been updated that
8837         // may require regenerating vertexmesh array...
8838         needsupdate = 0;
8839
8840         // check if any dynamic vertex processing must occur
8841         dynamicvertex = false;
8842
8843         // a cvar to force the dynamic vertex path to be taken, for debugging
8844         if (r_batch_debugdynamicvertexpath.integer)
8845         {
8846                 if (!dynamicvertex)
8847                 {
8848                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8849                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8850                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8851                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8852                 }
8853                 dynamicvertex = true;
8854         }
8855
8856         // if there is a chance of animated vertex colors, it's a dynamic batch
8857         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8858         {
8859                 if (!dynamicvertex)
8860                 {
8861                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8862                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8863                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8864                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8865                 }
8866                 dynamicvertex = true;
8867                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8868         }
8869
8870         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8871         {
8872                 switch (deform->deform)
8873                 {
8874                 default:
8875                 case Q3DEFORM_PROJECTIONSHADOW:
8876                 case Q3DEFORM_TEXT0:
8877                 case Q3DEFORM_TEXT1:
8878                 case Q3DEFORM_TEXT2:
8879                 case Q3DEFORM_TEXT3:
8880                 case Q3DEFORM_TEXT4:
8881                 case Q3DEFORM_TEXT5:
8882                 case Q3DEFORM_TEXT6:
8883                 case Q3DEFORM_TEXT7:
8884                 case Q3DEFORM_NONE:
8885                         break;
8886                 case Q3DEFORM_AUTOSPRITE:
8887                         if (!dynamicvertex)
8888                         {
8889                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8890                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8891                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8892                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8893                         }
8894                         dynamicvertex = true;
8895                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8896                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8897                         break;
8898                 case Q3DEFORM_AUTOSPRITE2:
8899                         if (!dynamicvertex)
8900                         {
8901                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8902                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8903                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8904                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8905                         }
8906                         dynamicvertex = true;
8907                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8908                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8909                         break;
8910                 case Q3DEFORM_NORMAL:
8911                         if (!dynamicvertex)
8912                         {
8913                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8914                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8915                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8916                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8917                         }
8918                         dynamicvertex = true;
8919                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8920                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8921                         break;
8922                 case Q3DEFORM_WAVE:
8923                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8924                                 break; // if wavefunc is a nop, ignore this transform
8925                         if (!dynamicvertex)
8926                         {
8927                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8928                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8929                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8930                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += 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_BULGE:
8937                         if (!dynamicvertex)
8938                         {
8939                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8940                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8941                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8942                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8943                         }
8944                         dynamicvertex = true;
8945                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8946                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8947                         break;
8948                 case Q3DEFORM_MOVE:
8949                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8950                                 break; // if wavefunc is a nop, ignore this transform
8951                         if (!dynamicvertex)
8952                         {
8953                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8954                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8955                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8956                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8957                         }
8958                         dynamicvertex = true;
8959                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8960                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8961                         break;
8962                 }
8963         }
8964         if (rsurface.texture->materialshaderpass)
8965         {
8966                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8967                 {
8968                 default:
8969                 case Q3TCGEN_TEXTURE:
8970                         break;
8971                 case Q3TCGEN_LIGHTMAP:
8972                         if (!dynamicvertex)
8973                         {
8974                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8975                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8976                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8977                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8978                         }
8979                         dynamicvertex = true;
8980                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8981                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8982                         break;
8983                 case Q3TCGEN_VECTOR:
8984                         if (!dynamicvertex)
8985                         {
8986                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8987                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8988                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8989                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8990                         }
8991                         dynamicvertex = true;
8992                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8993                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8994                         break;
8995                 case Q3TCGEN_ENVIRONMENT:
8996                         if (!dynamicvertex)
8997                         {
8998                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8999                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9000                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9001                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9002                         }
9003                         dynamicvertex = true;
9004                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9005                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9006                         break;
9007                 }
9008                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9009                 {
9010                         if (!dynamicvertex)
9011                         {
9012                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9013                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9014                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9015                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9016                         }
9017                         dynamicvertex = true;
9018                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9019                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9020                 }
9021         }
9022
9023         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9024         {
9025                 if (!dynamicvertex)
9026                 {
9027                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9028                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9029                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9030                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9031                 }
9032                 dynamicvertex = true;
9033                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9034         }
9035
9036         // when the model data has no vertex buffer (dynamic mesh), we need to
9037         // eliminate gaps
9038         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9039                 batchneed |= BATCHNEED_NOGAPS;
9040
9041         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9042         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9043         // we ensure this by treating the vertex batch as dynamic...
9044         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9045         {
9046                 if (!dynamicvertex)
9047                 {
9048                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9049                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9050                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9051                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9052                 }
9053                 dynamicvertex = true;
9054         }
9055
9056         if (dynamicvertex)
9057         {
9058                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9059                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9060                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9061                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9062                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9063                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9064                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9065                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9066         }
9067
9068         // if needsupdate, we have to do a dynamic vertex batch for sure
9069         if (needsupdate & batchneed)
9070         {
9071                 if (!dynamicvertex)
9072                 {
9073                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9074                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9075                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9076                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9077                 }
9078                 dynamicvertex = true;
9079         }
9080
9081         // see if we need to build vertexmesh from arrays
9082         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9083         {
9084                 if (!dynamicvertex)
9085                 {
9086                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9087                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9088                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9089                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9090                 }
9091                 dynamicvertex = true;
9092         }
9093
9094         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9095         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9096                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9097
9098         rsurface.batchvertex3f = rsurface.modelvertex3f;
9099         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9100         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9101         rsurface.batchsvector3f = rsurface.modelsvector3f;
9102         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9103         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9104         rsurface.batchtvector3f = rsurface.modeltvector3f;
9105         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9106         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9107         rsurface.batchnormal3f = rsurface.modelnormal3f;
9108         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9109         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9110         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9111         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9112         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9113         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9114         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9115         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9116         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9117         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9118         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9119         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9120         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9121         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9122         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9123         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9124         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9125         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9126         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9127         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9128         rsurface.batchelement3i = rsurface.modelelement3i;
9129         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9130         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9131         rsurface.batchelement3s = rsurface.modelelement3s;
9132         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9133         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9134         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9135         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9136         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9137         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9138         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9139
9140         // if any dynamic vertex processing has to occur in software, we copy the
9141         // entire surface list together before processing to rebase the vertices
9142         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9143         //
9144         // if any gaps exist and we do not have a static vertex buffer, we have to
9145         // copy the surface list together to avoid wasting upload bandwidth on the
9146         // vertices in the gaps.
9147         //
9148         // if gaps exist and we have a static vertex buffer, we can choose whether
9149         // to combine the index buffer ranges into one dynamic index buffer or
9150         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9151         //
9152         // in many cases the batch is reduced to one draw call.
9153
9154         rsurface.batchmultidraw = false;
9155         rsurface.batchmultidrawnumsurfaces = 0;
9156         rsurface.batchmultidrawsurfacelist = NULL;
9157
9158         if (!dynamicvertex)
9159         {
9160                 // static vertex data, just set pointers...
9161                 rsurface.batchgeneratedvertex = false;
9162                 // if there are gaps, we want to build a combined index buffer,
9163                 // otherwise use the original static buffer with an appropriate offset
9164                 if (gaps)
9165                 {
9166                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9167                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9168                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9169                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9170                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9171                         {
9172                                 rsurface.batchmultidraw = true;
9173                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9174                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9175                                 return;
9176                         }
9177                         // build a new triangle elements array for this batch
9178                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9179                         rsurface.batchfirsttriangle = 0;
9180                         numtriangles = 0;
9181                         for (i = 0;i < texturenumsurfaces;i++)
9182                         {
9183                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9184                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9185                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9186                                 numtriangles += surfacenumtriangles;
9187                         }
9188                         rsurface.batchelement3i_indexbuffer = NULL;
9189                         rsurface.batchelement3i_bufferoffset = 0;
9190                         rsurface.batchelement3s = NULL;
9191                         rsurface.batchelement3s_indexbuffer = NULL;
9192                         rsurface.batchelement3s_bufferoffset = 0;
9193                         if (endvertex <= 65536)
9194                         {
9195                                 // make a 16bit (unsigned short) index array if possible
9196                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9197                                 for (i = 0;i < numtriangles*3;i++)
9198                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9199                         }
9200                         // upload buffer data for the copytriangles batch
9201                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9202                         {
9203                                 if (rsurface.batchelement3s)
9204                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9205                                 else if (rsurface.batchelement3i)
9206                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9207                         }
9208                 }
9209                 else
9210                 {
9211                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9212                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9213                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9214                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9215                 }
9216                 return;
9217         }
9218
9219         // something needs software processing, do it for real...
9220         // we only directly handle separate array data in this case and then
9221         // generate interleaved data if needed...
9222         rsurface.batchgeneratedvertex = true;
9223         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9224         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9225         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9226         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9227
9228         // now copy the vertex data into a combined array and make an index array
9229         // (this is what Quake3 does all the time)
9230         // we also apply any skeletal animation here that would have been done in
9231         // the vertex shader, because most of the dynamic vertex animation cases
9232         // need actual vertex positions and normals
9233         //if (dynamicvertex)
9234         {
9235                 rsurface.batchvertexmesh = NULL;
9236                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9237                 rsurface.batchvertexmesh_bufferoffset = 0;
9238                 rsurface.batchvertex3f = NULL;
9239                 rsurface.batchvertex3f_vertexbuffer = NULL;
9240                 rsurface.batchvertex3f_bufferoffset = 0;
9241                 rsurface.batchsvector3f = NULL;
9242                 rsurface.batchsvector3f_vertexbuffer = NULL;
9243                 rsurface.batchsvector3f_bufferoffset = 0;
9244                 rsurface.batchtvector3f = NULL;
9245                 rsurface.batchtvector3f_vertexbuffer = NULL;
9246                 rsurface.batchtvector3f_bufferoffset = 0;
9247                 rsurface.batchnormal3f = NULL;
9248                 rsurface.batchnormal3f_vertexbuffer = NULL;
9249                 rsurface.batchnormal3f_bufferoffset = 0;
9250                 rsurface.batchlightmapcolor4f = NULL;
9251                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9252                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9253                 rsurface.batchtexcoordtexture2f = NULL;
9254                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9255                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9256                 rsurface.batchtexcoordlightmap2f = NULL;
9257                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9258                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9259                 rsurface.batchskeletalindex4ub = NULL;
9260                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9261                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9262                 rsurface.batchskeletalweight4ub = NULL;
9263                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9264                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9265                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9266                 rsurface.batchelement3i_indexbuffer = NULL;
9267                 rsurface.batchelement3i_bufferoffset = 0;
9268                 rsurface.batchelement3s = NULL;
9269                 rsurface.batchelement3s_indexbuffer = NULL;
9270                 rsurface.batchelement3s_bufferoffset = 0;
9271                 rsurface.batchskeletaltransform3x4buffer = NULL;
9272                 rsurface.batchskeletaltransform3x4offset = 0;
9273                 rsurface.batchskeletaltransform3x4size = 0;
9274                 // we'll only be setting up certain arrays as needed
9275                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9276                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9277                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9278                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9279                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9280                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9281                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9282                 {
9283                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9284                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9285                 }
9286                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9287                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9288                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9289                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9290                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9291                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9293                 {
9294                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9295                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9296                 }
9297                 numvertices = 0;
9298                 numtriangles = 0;
9299                 for (i = 0;i < texturenumsurfaces;i++)
9300                 {
9301                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9302                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9303                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9304                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9305                         // copy only the data requested
9306                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9307                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9308                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9309                         {
9310                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9311                                 {
9312                                         if (rsurface.batchvertex3f)
9313                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9314                                         else
9315                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9316                                 }
9317                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9318                                 {
9319                                         if (rsurface.modelnormal3f)
9320                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9321                                         else
9322                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9323                                 }
9324                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9325                                 {
9326                                         if (rsurface.modelsvector3f)
9327                                         {
9328                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9329                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9330                                         }
9331                                         else
9332                                         {
9333                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9334                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9335                                         }
9336                                 }
9337                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9338                                 {
9339                                         if (rsurface.modellightmapcolor4f)
9340                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9341                                         else
9342                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9343                                 }
9344                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9345                                 {
9346                                         if (rsurface.modeltexcoordtexture2f)
9347                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9348                                         else
9349                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9350                                 }
9351                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9352                                 {
9353                                         if (rsurface.modeltexcoordlightmap2f)
9354                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9355                                         else
9356                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9357                                 }
9358                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9359                                 {
9360                                         if (rsurface.modelskeletalindex4ub)
9361                                         {
9362                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9363                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9364                                         }
9365                                         else
9366                                         {
9367                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9368                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9369                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9370                                                 for (j = 0;j < surfacenumvertices;j++)
9371                                                         ub[j*4] = 255;
9372                                         }
9373                                 }
9374                         }
9375                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9376                         numvertices += surfacenumvertices;
9377                         numtriangles += surfacenumtriangles;
9378                 }
9379
9380                 // generate a 16bit index array as well if possible
9381                 // (in general, dynamic batches fit)
9382                 if (numvertices <= 65536)
9383                 {
9384                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9385                         for (i = 0;i < numtriangles*3;i++)
9386                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9387                 }
9388
9389                 // since we've copied everything, the batch now starts at 0
9390                 rsurface.batchfirstvertex = 0;
9391                 rsurface.batchnumvertices = batchnumvertices;
9392                 rsurface.batchfirsttriangle = 0;
9393                 rsurface.batchnumtriangles = batchnumtriangles;
9394         }
9395
9396         // apply skeletal animation that would have been done in the vertex shader
9397         if (rsurface.batchskeletaltransform3x4)
9398         {
9399                 const unsigned char *si;
9400                 const unsigned char *sw;
9401                 const float *t[4];
9402                 const float *b = rsurface.batchskeletaltransform3x4;
9403                 float *vp, *vs, *vt, *vn;
9404                 float w[4];
9405                 float m[3][4], n[3][4];
9406                 float tp[3], ts[3], tt[3], tn[3];
9407                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9408                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9409                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9410                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9411                 si = rsurface.batchskeletalindex4ub;
9412                 sw = rsurface.batchskeletalweight4ub;
9413                 vp = rsurface.batchvertex3f;
9414                 vs = rsurface.batchsvector3f;
9415                 vt = rsurface.batchtvector3f;
9416                 vn = rsurface.batchnormal3f;
9417                 memset(m[0], 0, sizeof(m));
9418                 memset(n[0], 0, sizeof(n));
9419                 for (i = 0;i < batchnumvertices;i++)
9420                 {
9421                         t[0] = b + si[0]*12;
9422                         if (sw[0] == 255)
9423                         {
9424                                 // common case - only one matrix
9425                                 m[0][0] = t[0][ 0];
9426                                 m[0][1] = t[0][ 1];
9427                                 m[0][2] = t[0][ 2];
9428                                 m[0][3] = t[0][ 3];
9429                                 m[1][0] = t[0][ 4];
9430                                 m[1][1] = t[0][ 5];
9431                                 m[1][2] = t[0][ 6];
9432                                 m[1][3] = t[0][ 7];
9433                                 m[2][0] = t[0][ 8];
9434                                 m[2][1] = t[0][ 9];
9435                                 m[2][2] = t[0][10];
9436                                 m[2][3] = t[0][11];
9437                         }
9438                         else if (sw[2] + sw[3])
9439                         {
9440                                 // blend 4 matrices
9441                                 t[1] = b + si[1]*12;
9442                                 t[2] = b + si[2]*12;
9443                                 t[3] = b + si[3]*12;
9444                                 w[0] = sw[0] * (1.0f / 255.0f);
9445                                 w[1] = sw[1] * (1.0f / 255.0f);
9446                                 w[2] = sw[2] * (1.0f / 255.0f);
9447                                 w[3] = sw[3] * (1.0f / 255.0f);
9448                                 // blend the matrices
9449                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9450                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9451                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9452                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9453                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9454                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9455                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9456                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9457                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9458                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9459                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9460                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9461                         }
9462                         else
9463                         {
9464                                 // blend 2 matrices
9465                                 t[1] = b + si[1]*12;
9466                                 w[0] = sw[0] * (1.0f / 255.0f);
9467                                 w[1] = sw[1] * (1.0f / 255.0f);
9468                                 // blend the matrices
9469                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9470                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9471                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9472                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9473                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9474                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9475                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9476                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9477                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9478                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9479                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9480                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9481                         }
9482                         si += 4;
9483                         sw += 4;
9484                         // modify the vertex
9485                         VectorCopy(vp, tp);
9486                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9487                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9488                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9489                         vp += 3;
9490                         if (vn)
9491                         {
9492                                 // the normal transformation matrix is a set of cross products...
9493                                 CrossProduct(m[1], m[2], n[0]);
9494                                 CrossProduct(m[2], m[0], n[1]);
9495                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9496                                 VectorCopy(vn, tn);
9497                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9498                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9499                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9500                                 VectorNormalize(vn);
9501                                 vn += 3;
9502                                 if (vs)
9503                                 {
9504                                         VectorCopy(vs, ts);
9505                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9506                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9507                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9508                                         VectorNormalize(vs);
9509                                         vs += 3;
9510                                         VectorCopy(vt, tt);
9511                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9512                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9513                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9514                                         VectorNormalize(vt);
9515                                         vt += 3;
9516                                 }
9517                         }
9518                 }
9519                 rsurface.batchskeletaltransform3x4 = NULL;
9520                 rsurface.batchskeletalnumtransforms = 0;
9521         }
9522
9523         // q1bsp surfaces rendered in vertex color mode have to have colors
9524         // calculated based on lightstyles
9525         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9526         {
9527                 // generate color arrays for the surfaces in this list
9528                 int c[4];
9529                 int scale;
9530                 int size3;
9531                 const int *offsets;
9532                 const unsigned char *lm;
9533                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9534                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9535                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9536                 numvertices = 0;
9537                 for (i = 0;i < texturenumsurfaces;i++)
9538                 {
9539                         surface = texturesurfacelist[i];
9540                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9541                         surfacenumvertices = surface->num_vertices;
9542                         if (surface->lightmapinfo->samples)
9543                         {
9544                                 for (j = 0;j < surfacenumvertices;j++)
9545                                 {
9546                                         lm = surface->lightmapinfo->samples + offsets[j];
9547                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9548                                         VectorScale(lm, scale, c);
9549                                         if (surface->lightmapinfo->styles[1] != 255)
9550                                         {
9551                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9552                                                 lm += size3;
9553                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9554                                                 VectorMA(c, scale, lm, c);
9555                                                 if (surface->lightmapinfo->styles[2] != 255)
9556                                                 {
9557                                                         lm += size3;
9558                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9559                                                         VectorMA(c, scale, lm, c);
9560                                                         if (surface->lightmapinfo->styles[3] != 255)
9561                                                         {
9562                                                                 lm += size3;
9563                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9564                                                                 VectorMA(c, scale, lm, c);
9565                                                         }
9566                                                 }
9567                                         }
9568                                         c[0] >>= 7;
9569                                         c[1] >>= 7;
9570                                         c[2] >>= 7;
9571                                         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);
9572                                         numvertices++;
9573                                 }
9574                         }
9575                         else
9576                         {
9577                                 for (j = 0;j < surfacenumvertices;j++)
9578                                 {
9579                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9580                                         numvertices++;
9581                                 }
9582                         }
9583                 }
9584         }
9585
9586         // if vertices are deformed (sprite flares and things in maps, possibly
9587         // water waves, bulges and other deformations), modify the copied vertices
9588         // in place
9589         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9590         {
9591                 float scale;
9592                 switch (deform->deform)
9593                 {
9594                 default:
9595                 case Q3DEFORM_PROJECTIONSHADOW:
9596                 case Q3DEFORM_TEXT0:
9597                 case Q3DEFORM_TEXT1:
9598                 case Q3DEFORM_TEXT2:
9599                 case Q3DEFORM_TEXT3:
9600                 case Q3DEFORM_TEXT4:
9601                 case Q3DEFORM_TEXT5:
9602                 case Q3DEFORM_TEXT6:
9603                 case Q3DEFORM_TEXT7:
9604                 case Q3DEFORM_NONE:
9605                         break;
9606                 case Q3DEFORM_AUTOSPRITE:
9607                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9608                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9609                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9610                         VectorNormalize(newforward);
9611                         VectorNormalize(newright);
9612                         VectorNormalize(newup);
9613 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9614 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9615 //                      rsurface.batchvertex3f_bufferoffset = 0;
9616 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9617 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9618 //                      rsurface.batchsvector3f_bufferoffset = 0;
9619 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9620 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9621 //                      rsurface.batchtvector3f_bufferoffset = 0;
9622 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9623 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9624 //                      rsurface.batchnormal3f_bufferoffset = 0;
9625                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9626                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9627                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9628                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9629                                 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);
9630                         // a single autosprite surface can contain multiple sprites...
9631                         for (j = 0;j < batchnumvertices - 3;j += 4)
9632                         {
9633                                 VectorClear(center);
9634                                 for (i = 0;i < 4;i++)
9635                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9636                                 VectorScale(center, 0.25f, center);
9637                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9638                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9639                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9640                                 for (i = 0;i < 4;i++)
9641                                 {
9642                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9643                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9644                                 }
9645                         }
9646                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9647                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9648                         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);
9649                         break;
9650                 case Q3DEFORM_AUTOSPRITE2:
9651                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9652                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9653                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9654                         VectorNormalize(newforward);
9655                         VectorNormalize(newright);
9656                         VectorNormalize(newup);
9657 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9658 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9659 //                      rsurface.batchvertex3f_bufferoffset = 0;
9660                         {
9661                                 const float *v1, *v2;
9662                                 vec3_t start, end;
9663                                 float f, l;
9664                                 struct
9665                                 {
9666                                         float length2;
9667                                         const float *v1;
9668                                         const float *v2;
9669                                 }
9670                                 shortest[2];
9671                                 memset(shortest, 0, sizeof(shortest));
9672                                 // a single autosprite surface can contain multiple sprites...
9673                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9674                                 {
9675                                         VectorClear(center);
9676                                         for (i = 0;i < 4;i++)
9677                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9678                                         VectorScale(center, 0.25f, center);
9679                                         // find the two shortest edges, then use them to define the
9680                                         // axis vectors for rotating around the central axis
9681                                         for (i = 0;i < 6;i++)
9682                                         {
9683                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9684                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9685                                                 l = VectorDistance2(v1, v2);
9686                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9687                                                 if (v1[2] != v2[2])
9688                                                         l += (1.0f / 1024.0f);
9689                                                 if (shortest[0].length2 > l || i == 0)
9690                                                 {
9691                                                         shortest[1] = shortest[0];
9692                                                         shortest[0].length2 = l;
9693                                                         shortest[0].v1 = v1;
9694                                                         shortest[0].v2 = v2;
9695                                                 }
9696                                                 else if (shortest[1].length2 > l || i == 1)
9697                                                 {
9698                                                         shortest[1].length2 = l;
9699                                                         shortest[1].v1 = v1;
9700                                                         shortest[1].v2 = v2;
9701                                                 }
9702                                         }
9703                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9704                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9705                                         // this calculates the right vector from the shortest edge
9706                                         // and the up vector from the edge midpoints
9707                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9708                                         VectorNormalize(right);
9709                                         VectorSubtract(end, start, up);
9710                                         VectorNormalize(up);
9711                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9712                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9713                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9714                                         VectorNegate(forward, forward);
9715                                         VectorReflect(forward, 0, up, forward);
9716                                         VectorNormalize(forward);
9717                                         CrossProduct(up, forward, newright);
9718                                         VectorNormalize(newright);
9719                                         // rotate the quad around the up axis vector, this is made
9720                                         // especially easy by the fact we know the quad is flat,
9721                                         // so we only have to subtract the center position and
9722                                         // measure distance along the right vector, and then
9723                                         // multiply that by the newright vector and add back the
9724                                         // center position
9725                                         // we also need to subtract the old position to undo the
9726                                         // displacement from the center, which we do with a
9727                                         // DotProduct, the subtraction/addition of center is also
9728                                         // optimized into DotProducts here
9729                                         l = DotProduct(right, center);
9730                                         for (i = 0;i < 4;i++)
9731                                         {
9732                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9733                                                 f = DotProduct(right, v1) - l;
9734                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9735                                         }
9736                                 }
9737                         }
9738                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9739                         {
9740 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9741 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9742 //                              rsurface.batchnormal3f_bufferoffset = 0;
9743                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9744                         }
9745                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9746                         {
9747 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9748 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9749 //                              rsurface.batchsvector3f_bufferoffset = 0;
9750 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9751 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9752 //                              rsurface.batchtvector3f_bufferoffset = 0;
9753                                 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);
9754                         }
9755                         break;
9756                 case Q3DEFORM_NORMAL:
9757                         // deform the normals to make reflections wavey
9758                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9759                         rsurface.batchnormal3f_vertexbuffer = NULL;
9760                         rsurface.batchnormal3f_bufferoffset = 0;
9761                         for (j = 0;j < batchnumvertices;j++)
9762                         {
9763                                 float vertex[3];
9764                                 float *normal = rsurface.batchnormal3f + 3*j;
9765                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9766                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9767                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9768                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9769                                 VectorNormalize(normal);
9770                         }
9771                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9772                         {
9773 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9774 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9775 //                              rsurface.batchsvector3f_bufferoffset = 0;
9776 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9777 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9778 //                              rsurface.batchtvector3f_bufferoffset = 0;
9779                                 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);
9780                         }
9781                         break;
9782                 case Q3DEFORM_WAVE:
9783                         // deform vertex array to make wavey water and flags and such
9784                         waveparms[0] = deform->waveparms[0];
9785                         waveparms[1] = deform->waveparms[1];
9786                         waveparms[2] = deform->waveparms[2];
9787                         waveparms[3] = deform->waveparms[3];
9788                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9789                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9790                         // this is how a divisor of vertex influence on deformation
9791                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9792                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9793 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9794 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9795 //                      rsurface.batchvertex3f_bufferoffset = 0;
9796 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9797 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9798 //                      rsurface.batchnormal3f_bufferoffset = 0;
9799                         for (j = 0;j < batchnumvertices;j++)
9800                         {
9801                                 // if the wavefunc depends on time, evaluate it per-vertex
9802                                 if (waveparms[3])
9803                                 {
9804                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9805                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9806                                 }
9807                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9808                         }
9809                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9810                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9811                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9812                         {
9813 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9814 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9815 //                              rsurface.batchsvector3f_bufferoffset = 0;
9816 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9817 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9818 //                              rsurface.batchtvector3f_bufferoffset = 0;
9819                                 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);
9820                         }
9821                         break;
9822                 case Q3DEFORM_BULGE:
9823                         // deform vertex array to make the surface have moving bulges
9824 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9825 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9826 //                      rsurface.batchvertex3f_bufferoffset = 0;
9827 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9828 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9829 //                      rsurface.batchnormal3f_bufferoffset = 0;
9830                         for (j = 0;j < batchnumvertices;j++)
9831                         {
9832                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9833                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9834                         }
9835                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9836                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9837                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9838                         {
9839 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9840 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9841 //                              rsurface.batchsvector3f_bufferoffset = 0;
9842 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9843 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9844 //                              rsurface.batchtvector3f_bufferoffset = 0;
9845                                 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);
9846                         }
9847                         break;
9848                 case Q3DEFORM_MOVE:
9849                         // deform vertex array
9850                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9851                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9852                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9853                         VectorScale(deform->parms, scale, waveparms);
9854 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9855 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9856 //                      rsurface.batchvertex3f_bufferoffset = 0;
9857                         for (j = 0;j < batchnumvertices;j++)
9858                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9859                         break;
9860                 }
9861         }
9862
9863         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9864         {
9865         // generate texcoords based on the chosen texcoord source
9866                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9867                 {
9868                 default:
9869                 case Q3TCGEN_TEXTURE:
9870                         break;
9871                 case Q3TCGEN_LIGHTMAP:
9872         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9873         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9874         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9875                         if (rsurface.batchtexcoordlightmap2f)
9876                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9877                         break;
9878                 case Q3TCGEN_VECTOR:
9879         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9880         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9881         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9882                         for (j = 0;j < batchnumvertices;j++)
9883                         {
9884                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9885                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9886                         }
9887                         break;
9888                 case Q3TCGEN_ENVIRONMENT:
9889                         // make environment reflections using a spheremap
9890                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9891                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9892                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9893                         for (j = 0;j < batchnumvertices;j++)
9894                         {
9895                                 // identical to Q3A's method, but executed in worldspace so
9896                                 // carried models can be shiny too
9897
9898                                 float viewer[3], d, reflected[3], worldreflected[3];
9899
9900                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9901                                 // VectorNormalize(viewer);
9902
9903                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9904
9905                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9906                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9907                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9908                                 // note: this is proportinal to viewer, so we can normalize later
9909
9910                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9911                                 VectorNormalize(worldreflected);
9912
9913                                 // note: this sphere map only uses world x and z!
9914                                 // so positive and negative y will LOOK THE SAME.
9915                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9916                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9917                         }
9918                         break;
9919                 }
9920                 // the only tcmod that needs software vertex processing is turbulent, so
9921                 // check for it here and apply the changes if needed
9922                 // and we only support that as the first one
9923                 // (handling a mixture of turbulent and other tcmods would be problematic
9924                 //  without punting it entirely to a software path)
9925                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9926                 {
9927                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9928                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9929         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9930         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9931         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9932                         for (j = 0;j < batchnumvertices;j++)
9933                         {
9934                                 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);
9935                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9936                         }
9937                 }
9938         }
9939
9940         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9941         {
9942                 // convert the modified arrays to vertex structs
9943 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9944 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
9945 //              rsurface.batchvertexmesh_bufferoffset = 0;
9946                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9947                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9948                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9949                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9950                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9951                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9952                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9953                 {
9954                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9955                         {
9956                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9957                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9958                         }
9959                 }
9960                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9961                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9962                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9963                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9964                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9965                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9966                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9967                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9968                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9969                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9970                 {
9971                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9972                         {
9973                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9974                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9975                         }
9976                 }
9977         }
9978
9979         // upload buffer data for the dynamic batch
9980         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9981         {
9982                 if (rsurface.batchvertexmesh)
9983                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
9984                 else
9985                 {
9986                         if (rsurface.batchvertex3f)
9987                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
9988                         if (rsurface.batchsvector3f)
9989                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
9990                         if (rsurface.batchtvector3f)
9991                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
9992                         if (rsurface.batchnormal3f)
9993                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
9994                         if (rsurface.batchlightmapcolor4f)
9995                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
9996                         if (rsurface.batchtexcoordtexture2f)
9997                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
9998                         if (rsurface.batchtexcoordlightmap2f)
9999                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10000                         if (rsurface.batchskeletalindex4ub)
10001                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10002                         if (rsurface.batchskeletalweight4ub)
10003                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10004                 }
10005                 if (rsurface.batchelement3s)
10006                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10007                 else if (rsurface.batchelement3i)
10008                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10009         }
10010 }
10011
10012 void RSurf_DrawBatch(void)
10013 {
10014         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10015         // through the pipeline, killing it earlier in the pipeline would have
10016         // per-surface overhead rather than per-batch overhead, so it's best to
10017         // reject it here, before it hits glDraw.
10018         if (rsurface.batchnumtriangles == 0)
10019                 return;
10020 #if 0
10021         // batch debugging code
10022         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10023         {
10024                 int i;
10025                 int j;
10026                 int c;
10027                 const int *e;
10028                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10029                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10030                 {
10031                         c = e[i];
10032                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10033                         {
10034                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10035                                 {
10036                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10037                                                 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);
10038                                         break;
10039                                 }
10040                         }
10041                 }
10042         }
10043 #endif
10044         if (rsurface.batchmultidraw)
10045         {
10046                 // issue multiple draws rather than copying index data
10047                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10048                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10049                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10050                 for (i = 0;i < numsurfaces;)
10051                 {
10052                         // combine consecutive surfaces as one draw
10053                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10054                                 if (surfacelist[j] != surfacelist[k] + 1)
10055                                         break;
10056                         firstvertex = surfacelist[i]->num_firstvertex;
10057                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10058                         firsttriangle = surfacelist[i]->num_firsttriangle;
10059                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10060                         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);
10061                         i = j;
10062                 }
10063         }
10064         else
10065         {
10066                 // there is only one consecutive run of index data (may have been combined)
10067                 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);
10068         }
10069 }
10070
10071 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10072 {
10073         // pick the closest matching water plane
10074         int planeindex, vertexindex, bestplaneindex = -1;
10075         float d, bestd;
10076         vec3_t vert;
10077         const float *v;
10078         r_waterstate_waterplane_t *p;
10079         qboolean prepared = false;
10080         bestd = 0;
10081         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10082         {
10083                 if(p->camera_entity != rsurface.texture->camera_entity)
10084                         continue;
10085                 d = 0;
10086                 if(!prepared)
10087                 {
10088                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10089                         prepared = true;
10090                         if(rsurface.batchnumvertices == 0)
10091                                 break;
10092                 }
10093                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10094                 {
10095                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10096                         d += fabs(PlaneDiff(vert, &p->plane));
10097                 }
10098                 if (bestd > d || bestplaneindex < 0)
10099                 {
10100                         bestd = d;
10101                         bestplaneindex = planeindex;
10102                 }
10103         }
10104         return bestplaneindex;
10105         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10106         // this situation though, as it might be better to render single larger
10107         // batches with useless stuff (backface culled for example) than to
10108         // render multiple smaller batches
10109 }
10110
10111 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10112 {
10113         int i;
10114         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10115         rsurface.passcolor4f_vertexbuffer = 0;
10116         rsurface.passcolor4f_bufferoffset = 0;
10117         for (i = 0;i < rsurface.batchnumvertices;i++)
10118                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10119 }
10120
10121 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10122 {
10123         int i;
10124         float f;
10125         const float *v;
10126         const float *c;
10127         float *c2;
10128         if (rsurface.passcolor4f)
10129         {
10130                 // generate color arrays
10131                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10132                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10133                 rsurface.passcolor4f_vertexbuffer = 0;
10134                 rsurface.passcolor4f_bufferoffset = 0;
10135                 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)
10136                 {
10137                         f = RSurf_FogVertex(v);
10138                         c2[0] = c[0] * f;
10139                         c2[1] = c[1] * f;
10140                         c2[2] = c[2] * f;
10141                         c2[3] = c[3];
10142                 }
10143         }
10144         else
10145         {
10146                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10147                 rsurface.passcolor4f_vertexbuffer = 0;
10148                 rsurface.passcolor4f_bufferoffset = 0;
10149                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10150                 {
10151                         f = RSurf_FogVertex(v);
10152                         c2[0] = f;
10153                         c2[1] = f;
10154                         c2[2] = f;
10155                         c2[3] = 1;
10156                 }
10157         }
10158 }
10159
10160 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10161 {
10162         int i;
10163         float f;
10164         const float *v;
10165         const float *c;
10166         float *c2;
10167         if (!rsurface.passcolor4f)
10168                 return;
10169         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10170         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10171         rsurface.passcolor4f_vertexbuffer = 0;
10172         rsurface.passcolor4f_bufferoffset = 0;
10173         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)
10174         {
10175                 f = RSurf_FogVertex(v);
10176                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10177                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10178                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10179                 c2[3] = c[3];
10180         }
10181 }
10182
10183 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10184 {
10185         int i;
10186         const float *c;
10187         float *c2;
10188         if (!rsurface.passcolor4f)
10189                 return;
10190         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10191         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10192         rsurface.passcolor4f_vertexbuffer = 0;
10193         rsurface.passcolor4f_bufferoffset = 0;
10194         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10195         {
10196                 c2[0] = c[0] * r;
10197                 c2[1] = c[1] * g;
10198                 c2[2] = c[2] * b;
10199                 c2[3] = c[3] * a;
10200         }
10201 }
10202
10203 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10204 {
10205         int i;
10206         const float *c;
10207         float *c2;
10208         if (!rsurface.passcolor4f)
10209                 return;
10210         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10211         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10212         rsurface.passcolor4f_vertexbuffer = 0;
10213         rsurface.passcolor4f_bufferoffset = 0;
10214         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10215         {
10216                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10217                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10218                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10219                 c2[3] = c[3];
10220         }
10221 }
10222
10223 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10224 {
10225         // TODO: optimize
10226         rsurface.passcolor4f = NULL;
10227         rsurface.passcolor4f_vertexbuffer = 0;
10228         rsurface.passcolor4f_bufferoffset = 0;
10229         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10230         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10231         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10232         GL_Color(r, g, b, a);
10233         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10234         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10235         R_Mesh_TexMatrix(0, NULL);
10236         RSurf_DrawBatch();
10237 }
10238
10239 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10240 {
10241         // TODO: optimize applyfog && applycolor case
10242         // just apply fog if necessary, and tint the fog color array if necessary
10243         rsurface.passcolor4f = NULL;
10244         rsurface.passcolor4f_vertexbuffer = 0;
10245         rsurface.passcolor4f_bufferoffset = 0;
10246         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10247         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10248         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10249         GL_Color(r, g, b, a);
10250         RSurf_DrawBatch();
10251 }
10252
10253 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10254 {
10255         // TODO: optimize
10256         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10257         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10258         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10259         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10260         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10261         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10262         GL_Color(r, g, b, a);
10263         RSurf_DrawBatch();
10264 }
10265
10266 static void RSurf_DrawBatch_GL11_ClampColor(void)
10267 {
10268         int i;
10269         const float *c1;
10270         float *c2;
10271         if (!rsurface.passcolor4f)
10272                 return;
10273         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10274         {
10275                 c2[0] = bound(0.0f, c1[0], 1.0f);
10276                 c2[1] = bound(0.0f, c1[1], 1.0f);
10277                 c2[2] = bound(0.0f, c1[2], 1.0f);
10278                 c2[3] = bound(0.0f, c1[3], 1.0f);
10279         }
10280 }
10281
10282 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10283 {
10284         int i;
10285         float f;
10286         const float *v;
10287         const float *n;
10288         float *c;
10289         //vec3_t eyedir;
10290
10291         // fake shading
10292         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10293         rsurface.passcolor4f_vertexbuffer = 0;
10294         rsurface.passcolor4f_bufferoffset = 0;
10295         for (i = 0, 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)
10296         {
10297                 f = -DotProduct(r_refdef.view.forward, n);
10298                 f = max(0, f);
10299                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10300                 f *= fakelightintensity;
10301                 Vector4Set(c, f, f, f, 1);
10302         }
10303 }
10304
10305 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10306 {
10307         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10308         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10309         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10310         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10311         GL_Color(r, g, b, a);
10312         RSurf_DrawBatch();
10313 }
10314
10315 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10316 {
10317         int i;
10318         float f;
10319         float alpha;
10320         const float *v;
10321         const float *n;
10322         float *c;
10323         vec3_t ambientcolor;
10324         vec3_t diffusecolor;
10325         vec3_t lightdir;
10326         // TODO: optimize
10327         // model lighting
10328         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10329         f = 0.5f * lightmapintensity;
10330         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10331         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10332         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10333         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10334         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10335         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10336         alpha = *a;
10337         if (VectorLength2(diffusecolor) > 0)
10338         {
10339                 // q3-style directional shading
10340                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10341                 rsurface.passcolor4f_vertexbuffer = 0;
10342                 rsurface.passcolor4f_bufferoffset = 0;
10343                 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)
10344                 {
10345                         if ((f = DotProduct(n, lightdir)) > 0)
10346                                 VectorMA(ambientcolor, f, diffusecolor, c);
10347                         else
10348                                 VectorCopy(ambientcolor, c);
10349                         c[3] = alpha;
10350                 }
10351                 *r = 1;
10352                 *g = 1;
10353                 *b = 1;
10354                 *a = 1;
10355                 *applycolor = false;
10356         }
10357         else
10358         {
10359                 *r = ambientcolor[0];
10360                 *g = ambientcolor[1];
10361                 *b = ambientcolor[2];
10362                 rsurface.passcolor4f = NULL;
10363                 rsurface.passcolor4f_vertexbuffer = 0;
10364                 rsurface.passcolor4f_bufferoffset = 0;
10365         }
10366 }
10367
10368 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10369 {
10370         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10371         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10372         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10373         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10374         GL_Color(r, g, b, a);
10375         RSurf_DrawBatch();
10376 }
10377
10378 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10379 {
10380         int i;
10381         float f;
10382         const float *v;
10383         float *c;
10384
10385         // fake shading
10386         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10387         rsurface.passcolor4f_vertexbuffer = 0;
10388         rsurface.passcolor4f_bufferoffset = 0;
10389
10390         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10391         {
10392                 f = 1 - RSurf_FogVertex(v);
10393                 c[0] = r;
10394                 c[1] = g;
10395                 c[2] = b;
10396                 c[3] = f * a;
10397         }
10398 }
10399
10400 void RSurf_SetupDepthAndCulling(void)
10401 {
10402         // submodels are biased to avoid z-fighting with world surfaces that they
10403         // may be exactly overlapping (avoids z-fighting artifacts on certain
10404         // doors and things in Quake maps)
10405         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10406         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10407         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10408         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10409 }
10410
10411 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10412 {
10413         int i, j;
10414         // transparent sky would be ridiculous
10415         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10416                 return;
10417         R_SetupShader_Generic_NoTexture(false, false);
10418         skyrenderlater = true;
10419         RSurf_SetupDepthAndCulling();
10420         GL_DepthMask(true);
10421
10422         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10423         if (r_sky_scissor.integer)
10424         {
10425                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10426                 for (i = 0; i < texturenumsurfaces; i++)
10427                 {
10428                         const msurface_t *surf = texturesurfacelist[i];
10429                         const float *v;
10430                         float p[3];
10431                         float mins[3], maxs[3];
10432                         int scissor[4];
10433                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10434                         {
10435                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10436                                 if (j > 0)
10437                                 {
10438                                         if (mins[0] > p[0]) mins[0] = p[0];
10439                                         if (mins[1] > p[1]) mins[1] = p[1];
10440                                         if (mins[2] > p[2]) mins[2] = p[2];
10441                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10442                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10443                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10444                                 }
10445                                 else
10446                                 {
10447                                         VectorCopy(p, mins);
10448                                         VectorCopy(p, maxs);
10449                                 }
10450                         }
10451                         if (!R_ScissorForBBox(mins, maxs, scissor))
10452                         {
10453                                 if (skyscissor[2])
10454                                 {
10455                                         if (skyscissor[0] > scissor[0])
10456                                         {
10457                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10458                                                 skyscissor[0] = scissor[0];
10459                                         }
10460                                         if (skyscissor[1] > scissor[1])
10461                                         {
10462                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10463                                                 skyscissor[1] = scissor[1];
10464                                         }
10465                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10466                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10467                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10468                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10469                                 }
10470                                 else
10471                                         Vector4Copy(scissor, skyscissor);
10472                         }
10473                 }
10474         }
10475
10476         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10477         // skymasking on them, and Quake3 never did sky masking (unlike
10478         // software Quake and software Quake2), so disable the sky masking
10479         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10480         // and skymasking also looks very bad when noclipping outside the
10481         // level, so don't use it then either.
10482         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)
10483         {
10484                 R_Mesh_ResetTextureState();
10485                 if (skyrendermasked)
10486                 {
10487                         R_SetupShader_DepthOrShadow(false, false, false);
10488                         // depth-only (masking)
10489                         GL_ColorMask(0, 0, 0, 0);
10490                         // just to make sure that braindead drivers don't draw
10491                         // anything despite that colormask...
10492                         GL_BlendFunc(GL_ZERO, GL_ONE);
10493                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10494                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10495                 }
10496                 else
10497                 {
10498                         R_SetupShader_Generic_NoTexture(false, false);
10499                         // fog sky
10500                         GL_BlendFunc(GL_ONE, GL_ZERO);
10501                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10502                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10503                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10504                 }
10505                 RSurf_DrawBatch();
10506                 if (skyrendermasked)
10507                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10508         }
10509         R_Mesh_ResetTextureState();
10510         GL_Color(1, 1, 1, 1);
10511 }
10512
10513 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10514 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10515 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10516 {
10517         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10518                 return;
10519         if (prepass)
10520         {
10521                 // render screenspace normalmap to texture
10522                 GL_DepthMask(true);
10523                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10524                 RSurf_DrawBatch();
10525                 return;
10526         }
10527
10528         // bind lightmap texture
10529
10530         // water/refraction/reflection/camera surfaces have to be handled specially
10531         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10532         {
10533                 int start, end, startplaneindex;
10534                 for (start = 0;start < texturenumsurfaces;start = end)
10535                 {
10536                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10537                         if(startplaneindex < 0)
10538                         {
10539                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10540                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10541                                 end = start + 1;
10542                                 continue;
10543                         }
10544                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10545                                 ;
10546                         // now that we have a batch using the same planeindex, render it
10547                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10548                         {
10549                                 // render water or distortion background
10550                                 GL_DepthMask(true);
10551                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10552                                 RSurf_DrawBatch();
10553                                 // blend surface on top
10554                                 GL_DepthMask(false);
10555                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10556                                 RSurf_DrawBatch();
10557                         }
10558                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10559                         {
10560                                 // render surface with reflection texture as input
10561                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10562                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10563                                 RSurf_DrawBatch();
10564                         }
10565                 }
10566                 return;
10567         }
10568
10569         // render surface batch normally
10570         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10571         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10572         RSurf_DrawBatch();
10573 }
10574
10575 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10576 {
10577         // OpenGL 1.3 path - anything not completely ancient
10578         qboolean applycolor;
10579         qboolean applyfog;
10580         int layerindex;
10581         const texturelayer_t *layer;
10582         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);
10583         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10584
10585         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10586         {
10587                 vec4_t layercolor;
10588                 int layertexrgbscale;
10589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10590                 {
10591                         if (layerindex == 0)
10592                                 GL_AlphaTest(true);
10593                         else
10594                         {
10595                                 GL_AlphaTest(false);
10596                                 GL_DepthFunc(GL_EQUAL);
10597                         }
10598                 }
10599                 GL_DepthMask(layer->depthmask && writedepth);
10600                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10601                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10602                 {
10603                         layertexrgbscale = 4;
10604                         VectorScale(layer->color, 0.25f, layercolor);
10605                 }
10606                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10607                 {
10608                         layertexrgbscale = 2;
10609                         VectorScale(layer->color, 0.5f, layercolor);
10610                 }
10611                 else
10612                 {
10613                         layertexrgbscale = 1;
10614                         VectorScale(layer->color, 1.0f, layercolor);
10615                 }
10616                 layercolor[3] = layer->color[3];
10617                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10618                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10619                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10620                 switch (layer->type)
10621                 {
10622                 case TEXTURELAYERTYPE_LITTEXTURE:
10623                         // single-pass lightmapped texture with 2x rgbscale
10624                         R_Mesh_TexBind(0, r_texture_white);
10625                         R_Mesh_TexMatrix(0, NULL);
10626                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10627                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10628                         R_Mesh_TexBind(1, layer->texture);
10629                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10630                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10631                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10632                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10633                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10634                         else if (FAKELIGHT_ENABLED)
10635                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10636                         else if (rsurface.uselightmaptexture)
10637                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10638                         else
10639                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10640                         break;
10641                 case TEXTURELAYERTYPE_TEXTURE:
10642                         // singletexture unlit texture with transparency support
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                         R_Mesh_TexBind(1, 0);
10648                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10649                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10650                         break;
10651                 case TEXTURELAYERTYPE_FOG:
10652                         // singletexture fogging
10653                         if (layer->texture)
10654                         {
10655                                 R_Mesh_TexBind(0, layer->texture);
10656                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10657                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10658                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10659                         }
10660                         else
10661                         {
10662                                 R_Mesh_TexBind(0, 0);
10663                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10664                         }
10665                         R_Mesh_TexBind(1, 0);
10666                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10667                         // generate a color array for the fog pass
10668                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10669                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10670                         RSurf_DrawBatch();
10671                         break;
10672                 default:
10673                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10674                 }
10675         }
10676         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10677         {
10678                 GL_DepthFunc(GL_LEQUAL);
10679                 GL_AlphaTest(false);
10680         }
10681 }
10682
10683 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10684 {
10685         // OpenGL 1.1 - crusty old voodoo path
10686         qboolean applyfog;
10687         int layerindex;
10688         const texturelayer_t *layer;
10689         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);
10690         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10691
10692         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10693         {
10694                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10695                 {
10696                         if (layerindex == 0)
10697                                 GL_AlphaTest(true);
10698                         else
10699                         {
10700                                 GL_AlphaTest(false);
10701                                 GL_DepthFunc(GL_EQUAL);
10702                         }
10703                 }
10704                 GL_DepthMask(layer->depthmask && writedepth);
10705                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10706                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10707                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10708                 switch (layer->type)
10709                 {
10710                 case TEXTURELAYERTYPE_LITTEXTURE:
10711                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10712                         {
10713                                 // two-pass lit texture with 2x rgbscale
10714                                 // first the lightmap pass
10715                                 R_Mesh_TexBind(0, r_texture_white);
10716                                 R_Mesh_TexMatrix(0, NULL);
10717                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10718                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10719                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10720                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10721                                 else if (FAKELIGHT_ENABLED)
10722                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10723                                 else if (rsurface.uselightmaptexture)
10724                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10725                                 else
10726                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10727                                 // then apply the texture to it
10728                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10729                                 R_Mesh_TexBind(0, layer->texture);
10730                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10731                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10732                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10733                                 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);
10734                         }
10735                         else
10736                         {
10737                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10738                                 R_Mesh_TexBind(0, layer->texture);
10739                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10740                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10741                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10742                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10743                                         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);
10744                                 else if (FAKELIGHT_ENABLED)
10745                                         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);
10746                                 else
10747                                         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);
10748                         }
10749                         break;
10750                 case TEXTURELAYERTYPE_TEXTURE:
10751                         // singletexture unlit texture with transparency support
10752                         R_Mesh_TexBind(0, layer->texture);
10753                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10754                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10755                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10756                         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);
10757                         break;
10758                 case TEXTURELAYERTYPE_FOG:
10759                         // singletexture fogging
10760                         if (layer->texture)
10761                         {
10762                                 R_Mesh_TexBind(0, layer->texture);
10763                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10764                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10765                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10766                         }
10767                         else
10768                         {
10769                                 R_Mesh_TexBind(0, 0);
10770                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10771                         }
10772                         // generate a color array for the fog pass
10773                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10774                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10775                         RSurf_DrawBatch();
10776                         break;
10777                 default:
10778                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10779                 }
10780         }
10781         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10782         {
10783                 GL_DepthFunc(GL_LEQUAL);
10784                 GL_AlphaTest(false);
10785         }
10786 }
10787
10788 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10789 {
10790         int vi;
10791         int j;
10792         r_vertexgeneric_t *batchvertex;
10793         float c[4];
10794         texture_t *t = rsurface.texture;
10795
10796 //      R_Mesh_ResetTextureState();
10797         R_SetupShader_Generic_NoTexture(false, false);
10798
10799         if(t && t->currentskinframe)
10800         {
10801                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10802                 c[3] *= t->currentalpha;
10803         }
10804         else
10805         {
10806                 c[0] = 1;
10807                 c[1] = 0;
10808                 c[2] = 1;
10809                 c[3] = 1;
10810         }
10811
10812         if (t->pantstexture || t->shirttexture)
10813         {
10814                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10815                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10816                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10817         }
10818
10819         // brighten it up (as texture value 127 means "unlit")
10820         c[0] *= 2 * r_refdef.view.colorscale;
10821         c[1] *= 2 * r_refdef.view.colorscale;
10822         c[2] *= 2 * r_refdef.view.colorscale;
10823
10824         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10825                 c[3] *= r_wateralpha.value;
10826
10827         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10828         {
10829                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10830                 GL_DepthMask(false);
10831         }
10832         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10833         {
10834                 GL_BlendFunc(GL_ONE, GL_ONE);
10835                 GL_DepthMask(false);
10836         }
10837         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10838         {
10839                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10840                 GL_DepthMask(false);
10841         }
10842         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10843         {
10844                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10845                 GL_DepthMask(false);
10846         }
10847         else
10848         {
10849                 GL_BlendFunc(GL_ONE, GL_ZERO);
10850                 GL_DepthMask(writedepth);
10851         }
10852
10853         if (r_showsurfaces.integer == 3)
10854         {
10855                 rsurface.passcolor4f = NULL;
10856
10857                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10858                 {
10859                         qboolean applycolor = true;
10860                         float one = 1.0;
10861
10862                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10863
10864                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10865                 }
10866                 else if (FAKELIGHT_ENABLED)
10867                 {
10868                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10869
10870                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10871                 }
10872                 else
10873                 {
10874                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10875
10876                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10877                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10878                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10879                         RSurf_DrawBatch_GL11_ApplyAmbient();
10880                 }
10881
10882                 if(!rsurface.passcolor4f)
10883                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10884
10885                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10886                 if(r_refdef.fogenabled)
10887                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10888                 RSurf_DrawBatch_GL11_ClampColor();
10889
10890                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10891                 R_SetupShader_Generic_NoTexture(false, false);
10892                 RSurf_DrawBatch();
10893         }
10894         else if (!r_refdef.view.showdebug)
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                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10901                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10902                 }
10903                 R_Mesh_PrepareVertices_Generic_Unlock();
10904                 RSurf_DrawBatch();
10905         }
10906         else if (r_showsurfaces.integer == 4)
10907         {
10908                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10909                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10910                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10911                 {
10912                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
10913                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10914                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10915                 }
10916                 R_Mesh_PrepareVertices_Generic_Unlock();
10917                 RSurf_DrawBatch();
10918         }
10919         else if (r_showsurfaces.integer == 2)
10920         {
10921                 const int *e;
10922                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10923                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10924                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10925                 {
10926                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10927                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10928                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10929                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10930                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10931                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10932                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10933                 }
10934                 R_Mesh_PrepareVertices_Generic_Unlock();
10935                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10936         }
10937         else
10938         {
10939                 int texturesurfaceindex;
10940                 int k;
10941                 const msurface_t *surface;
10942                 float surfacecolor4f[4];
10943                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10944                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10945                 vi = 0;
10946                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10947                 {
10948                         surface = texturesurfacelist[texturesurfaceindex];
10949                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10950                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10951                         for (j = 0;j < surface->num_vertices;j++)
10952                         {
10953                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10954                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10955                                 vi++;
10956                         }
10957                 }
10958                 R_Mesh_PrepareVertices_Generic_Unlock();
10959                 RSurf_DrawBatch();
10960         }
10961 }
10962
10963 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10964 {
10965         CHECKGLERROR
10966         RSurf_SetupDepthAndCulling();
10967         if (r_showsurfaces.integer)
10968         {
10969                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10970                 return;
10971         }
10972         switch (vid.renderpath)
10973         {
10974         case RENDERPATH_GL20:
10975         case RENDERPATH_D3D9:
10976         case RENDERPATH_D3D10:
10977         case RENDERPATH_D3D11:
10978         case RENDERPATH_SOFT:
10979         case RENDERPATH_GLES2:
10980                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10981                 break;
10982         case RENDERPATH_GL13:
10983         case RENDERPATH_GLES1:
10984                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10985                 break;
10986         case RENDERPATH_GL11:
10987                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10988                 break;
10989         }
10990         CHECKGLERROR
10991 }
10992
10993 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10994 {
10995         int i, j;
10996         int texturenumsurfaces, endsurface;
10997         texture_t *texture;
10998         const msurface_t *surface;
10999         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11000
11001         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11002                 RSurf_ActiveModelEntity(ent, false, false, false);
11003         else
11004         {
11005                 switch (vid.renderpath)
11006                 {
11007                 case RENDERPATH_GL20:
11008                 case RENDERPATH_D3D9:
11009                 case RENDERPATH_D3D10:
11010                 case RENDERPATH_D3D11:
11011                 case RENDERPATH_SOFT:
11012                 case RENDERPATH_GLES2:
11013                         RSurf_ActiveModelEntity(ent, true, true, false);
11014                         break;
11015                 case RENDERPATH_GL11:
11016                 case RENDERPATH_GL13:
11017                 case RENDERPATH_GLES1:
11018                         RSurf_ActiveModelEntity(ent, true, false, false);
11019                         break;
11020                 }
11021         }
11022
11023         if (r_transparentdepthmasking.integer)
11024         {
11025                 qboolean setup = false;
11026                 for (i = 0;i < numsurfaces;i = j)
11027                 {
11028                         j = i + 1;
11029                         surface = rsurface.modelsurfaces + surfacelist[i];
11030                         texture = surface->texture;
11031                         rsurface.texture = R_GetCurrentTexture(texture);
11032                         rsurface.lightmaptexture = NULL;
11033                         rsurface.deluxemaptexture = NULL;
11034                         rsurface.uselightmaptexture = false;
11035                         // scan ahead until we find a different texture
11036                         endsurface = min(i + 1024, numsurfaces);
11037                         texturenumsurfaces = 0;
11038                         texturesurfacelist[texturenumsurfaces++] = surface;
11039                         for (;j < endsurface;j++)
11040                         {
11041                                 surface = rsurface.modelsurfaces + surfacelist[j];
11042                                 if (texture != surface->texture)
11043                                         break;
11044                                 texturesurfacelist[texturenumsurfaces++] = surface;
11045                         }
11046                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11047                                 continue;
11048                         // render the range of surfaces as depth
11049                         if (!setup)
11050                         {
11051                                 setup = true;
11052                                 GL_ColorMask(0,0,0,0);
11053                                 GL_Color(1,1,1,1);
11054                                 GL_DepthTest(true);
11055                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11056                                 GL_DepthMask(true);
11057 //                              R_Mesh_ResetTextureState();
11058                         }
11059                         RSurf_SetupDepthAndCulling();
11060                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11061                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11062                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11063                         RSurf_DrawBatch();
11064                 }
11065                 if (setup)
11066                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11067         }
11068
11069         for (i = 0;i < numsurfaces;i = j)
11070         {
11071                 j = i + 1;
11072                 surface = rsurface.modelsurfaces + surfacelist[i];
11073                 texture = surface->texture;
11074                 rsurface.texture = R_GetCurrentTexture(texture);
11075                 // scan ahead until we find a different texture
11076                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11077                 texturenumsurfaces = 0;
11078                 texturesurfacelist[texturenumsurfaces++] = surface;
11079                 if(FAKELIGHT_ENABLED)
11080                 {
11081                         rsurface.lightmaptexture = NULL;
11082                         rsurface.deluxemaptexture = NULL;
11083                         rsurface.uselightmaptexture = false;
11084                         for (;j < endsurface;j++)
11085                         {
11086                                 surface = rsurface.modelsurfaces + surfacelist[j];
11087                                 if (texture != surface->texture)
11088                                         break;
11089                                 texturesurfacelist[texturenumsurfaces++] = surface;
11090                         }
11091                 }
11092                 else
11093                 {
11094                         rsurface.lightmaptexture = surface->lightmaptexture;
11095                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11096                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11097                         for (;j < endsurface;j++)
11098                         {
11099                                 surface = rsurface.modelsurfaces + surfacelist[j];
11100                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11101                                         break;
11102                                 texturesurfacelist[texturenumsurfaces++] = surface;
11103                         }
11104                 }
11105                 // render the range of surfaces
11106                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11107         }
11108         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11109 }
11110
11111 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11112 {
11113         // transparent surfaces get pushed off into the transparent queue
11114         int surfacelistindex;
11115         const msurface_t *surface;
11116         vec3_t tempcenter, center;
11117         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11118         {
11119                 surface = texturesurfacelist[surfacelistindex];
11120                 if (r_transparent_sortsurfacesbynearest.integer)
11121                 {
11122                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11123                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11124                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11125                 }
11126                 else
11127                 {
11128                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11129                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11130                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11131                 }
11132                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11133                 if (rsurface.entity->transparent_offset) // transparent offset
11134                 {
11135                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11136                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11137                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11138                 }
11139                 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);
11140         }
11141 }
11142
11143 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11144 {
11145         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11146                 return;
11147         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11148                 return;
11149         RSurf_SetupDepthAndCulling();
11150         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11151         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11152         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11153         RSurf_DrawBatch();
11154 }
11155
11156 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11157 {
11158         CHECKGLERROR
11159         if (depthonly)
11160                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11161         else if (prepass)
11162         {
11163                 if (!rsurface.texture->currentnumlayers)
11164                         return;
11165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11166                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11167                 else
11168                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11169         }
11170         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11171                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11172         else if (!rsurface.texture->currentnumlayers)
11173                 return;
11174         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11175         {
11176                 // in the deferred case, transparent surfaces were queued during prepass
11177                 if (!r_shadow_usingdeferredprepass)
11178                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11179         }
11180         else
11181         {
11182                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11183                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11184         }
11185         CHECKGLERROR
11186 }
11187
11188 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11189 {
11190         int i, j;
11191         texture_t *texture;
11192         R_FrameData_SetMark();
11193         // break the surface list down into batches by texture and use of lightmapping
11194         for (i = 0;i < numsurfaces;i = j)
11195         {
11196                 j = i + 1;
11197                 // texture is the base texture pointer, rsurface.texture is the
11198                 // current frame/skin the texture is directing us to use (for example
11199                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11200                 // use skin 1 instead)
11201                 texture = surfacelist[i]->texture;
11202                 rsurface.texture = R_GetCurrentTexture(texture);
11203                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11204                 {
11205                         // if this texture is not the kind we want, skip ahead to the next one
11206                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11207                                 ;
11208                         continue;
11209                 }
11210                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11211                 {
11212                         rsurface.lightmaptexture = NULL;
11213                         rsurface.deluxemaptexture = NULL;
11214                         rsurface.uselightmaptexture = false;
11215                         // simply scan ahead until we find a different texture or lightmap state
11216                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11217                                 ;
11218                 }
11219                 else
11220                 {
11221                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11222                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11223                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11224                         // simply scan ahead until we find a different texture or lightmap state
11225                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11226                                 ;
11227                 }
11228                 // render the range of surfaces
11229                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11230         }
11231         R_FrameData_ReturnToMark();
11232 }
11233
11234 float locboxvertex3f[6*4*3] =
11235 {
11236         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11237         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11238         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11239         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11240         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11241         1,0,0, 0,0,0, 0,1,0, 1,1,0
11242 };
11243
11244 unsigned short locboxelements[6*2*3] =
11245 {
11246          0, 1, 2, 0, 2, 3,
11247          4, 5, 6, 4, 6, 7,
11248          8, 9,10, 8,10,11,
11249         12,13,14, 12,14,15,
11250         16,17,18, 16,18,19,
11251         20,21,22, 20,22,23
11252 };
11253
11254 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11255 {
11256         int i, j;
11257         cl_locnode_t *loc = (cl_locnode_t *)ent;
11258         vec3_t mins, size;
11259         float vertex3f[6*4*3];
11260         CHECKGLERROR
11261         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11262         GL_DepthMask(false);
11263         GL_DepthRange(0, 1);
11264         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11265         GL_DepthTest(true);
11266         GL_CullFace(GL_NONE);
11267         R_EntityMatrix(&identitymatrix);
11268
11269 //      R_Mesh_ResetTextureState();
11270
11271         i = surfacelist[0];
11272         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11273                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11274                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11275                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11276
11277         if (VectorCompare(loc->mins, loc->maxs))
11278         {
11279                 VectorSet(size, 2, 2, 2);
11280                 VectorMA(loc->mins, -0.5f, size, mins);
11281         }
11282         else
11283         {
11284                 VectorCopy(loc->mins, mins);
11285                 VectorSubtract(loc->maxs, loc->mins, size);
11286         }
11287
11288         for (i = 0;i < 6*4*3;)
11289                 for (j = 0;j < 3;j++, i++)
11290                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11291
11292         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11293         R_SetupShader_Generic_NoTexture(false, false);
11294         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11295 }
11296
11297 void R_DrawLocs(void)
11298 {
11299         int index;
11300         cl_locnode_t *loc, *nearestloc;
11301         vec3_t center;
11302         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11303         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11304         {
11305                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11306                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11307         }
11308 }
11309
11310 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11311 {
11312         if (decalsystem->decals)
11313                 Mem_Free(decalsystem->decals);
11314         memset(decalsystem, 0, sizeof(*decalsystem));
11315 }
11316
11317 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)
11318 {
11319         tridecal_t *decal;
11320         tridecal_t *decals;
11321         int i;
11322
11323         // expand or initialize the system
11324         if (decalsystem->maxdecals <= decalsystem->numdecals)
11325         {
11326                 decalsystem_t old = *decalsystem;
11327                 qboolean useshortelements;
11328                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11329                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11330                 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)));
11331                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11332                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11333                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11334                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11335                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11336                 if (decalsystem->numdecals)
11337                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11338                 if (old.decals)
11339                         Mem_Free(old.decals);
11340                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11341                         decalsystem->element3i[i] = i;
11342                 if (useshortelements)
11343                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11344                                 decalsystem->element3s[i] = i;
11345         }
11346
11347         // grab a decal and search for another free slot for the next one
11348         decals = decalsystem->decals;
11349         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11350         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11351                 ;
11352         decalsystem->freedecal = i;
11353         if (decalsystem->numdecals <= i)
11354                 decalsystem->numdecals = i + 1;
11355
11356         // initialize the decal
11357         decal->lived = 0;
11358         decal->triangleindex = triangleindex;
11359         decal->surfaceindex = surfaceindex;
11360         decal->decalsequence = decalsequence;
11361         decal->color4f[0][0] = c0[0];
11362         decal->color4f[0][1] = c0[1];
11363         decal->color4f[0][2] = c0[2];
11364         decal->color4f[0][3] = 1;
11365         decal->color4f[1][0] = c1[0];
11366         decal->color4f[1][1] = c1[1];
11367         decal->color4f[1][2] = c1[2];
11368         decal->color4f[1][3] = 1;
11369         decal->color4f[2][0] = c2[0];
11370         decal->color4f[2][1] = c2[1];
11371         decal->color4f[2][2] = c2[2];
11372         decal->color4f[2][3] = 1;
11373         decal->vertex3f[0][0] = v0[0];
11374         decal->vertex3f[0][1] = v0[1];
11375         decal->vertex3f[0][2] = v0[2];
11376         decal->vertex3f[1][0] = v1[0];
11377         decal->vertex3f[1][1] = v1[1];
11378         decal->vertex3f[1][2] = v1[2];
11379         decal->vertex3f[2][0] = v2[0];
11380         decal->vertex3f[2][1] = v2[1];
11381         decal->vertex3f[2][2] = v2[2];
11382         decal->texcoord2f[0][0] = t0[0];
11383         decal->texcoord2f[0][1] = t0[1];
11384         decal->texcoord2f[1][0] = t1[0];
11385         decal->texcoord2f[1][1] = t1[1];
11386         decal->texcoord2f[2][0] = t2[0];
11387         decal->texcoord2f[2][1] = t2[1];
11388         TriangleNormal(v0, v1, v2, decal->plane);
11389         VectorNormalize(decal->plane);
11390         decal->plane[3] = DotProduct(v0, decal->plane);
11391 }
11392
11393 extern cvar_t cl_decals_bias;
11394 extern cvar_t cl_decals_models;
11395 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11396 // baseparms, parms, temps
11397 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)
11398 {
11399         int cornerindex;
11400         int index;
11401         float v[9][3];
11402         const float *vertex3f;
11403         const float *normal3f;
11404         int numpoints;
11405         float points[2][9][3];
11406         float temp[3];
11407         float tc[9][2];
11408         float f;
11409         float c[9][4];
11410         const int *e;
11411
11412         e = rsurface.modelelement3i + 3*triangleindex;
11413
11414         vertex3f = rsurface.modelvertex3f;
11415         normal3f = rsurface.modelnormal3f;
11416
11417         if (normal3f)
11418         {
11419                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11420                 {
11421                         index = 3*e[cornerindex];
11422                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11423                 }
11424         }
11425         else
11426         {
11427                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11428                 {
11429                         index = 3*e[cornerindex];
11430                         VectorCopy(vertex3f + index, v[cornerindex]);
11431                 }
11432         }
11433
11434         // cull backfaces
11435         //TriangleNormal(v[0], v[1], v[2], normal);
11436         //if (DotProduct(normal, localnormal) < 0.0f)
11437         //      continue;
11438         // clip by each of the box planes formed from the projection matrix
11439         // if anything survives, we emit the decal
11440         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]);
11441         if (numpoints < 3)
11442                 return;
11443         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]);
11444         if (numpoints < 3)
11445                 return;
11446         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]);
11447         if (numpoints < 3)
11448                 return;
11449         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]);
11450         if (numpoints < 3)
11451                 return;
11452         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]);
11453         if (numpoints < 3)
11454                 return;
11455         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]);
11456         if (numpoints < 3)
11457                 return;
11458         // some part of the triangle survived, so we have to accept it...
11459         if (dynamic)
11460         {
11461                 // dynamic always uses the original triangle
11462                 numpoints = 3;
11463                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11464                 {
11465                         index = 3*e[cornerindex];
11466                         VectorCopy(vertex3f + index, v[cornerindex]);
11467                 }
11468         }
11469         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11470         {
11471                 // convert vertex positions to texcoords
11472                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11473                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11474                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11475                 // calculate distance fade from the projection origin
11476                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11477                 f = bound(0.0f, f, 1.0f);
11478                 c[cornerindex][0] = r * f;
11479                 c[cornerindex][1] = g * f;
11480                 c[cornerindex][2] = b * f;
11481                 c[cornerindex][3] = 1.0f;
11482                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11483         }
11484         if (dynamic)
11485                 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);
11486         else
11487                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11488                         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);
11489 }
11490 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)
11491 {
11492         matrix4x4_t projection;
11493         decalsystem_t *decalsystem;
11494         qboolean dynamic;
11495         dp_model_t *model;
11496         const msurface_t *surface;
11497         const msurface_t *surfaces;
11498         const int *surfacelist;
11499         const texture_t *texture;
11500         int numtriangles;
11501         int numsurfacelist;
11502         int surfacelistindex;
11503         int surfaceindex;
11504         int triangleindex;
11505         float localorigin[3];
11506         float localnormal[3];
11507         float localmins[3];
11508         float localmaxs[3];
11509         float localsize;
11510         //float normal[3];
11511         float planes[6][4];
11512         float angles[3];
11513         bih_t *bih;
11514         int bih_triangles_count;
11515         int bih_triangles[256];
11516         int bih_surfaces[256];
11517
11518         decalsystem = &ent->decalsystem;
11519         model = ent->model;
11520         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11521         {
11522                 R_DecalSystem_Reset(&ent->decalsystem);
11523                 return;
11524         }
11525
11526         if (!model->brush.data_leafs && !cl_decals_models.integer)
11527         {
11528                 if (decalsystem->model)
11529                         R_DecalSystem_Reset(decalsystem);
11530                 return;
11531         }
11532
11533         if (decalsystem->model != model)
11534                 R_DecalSystem_Reset(decalsystem);
11535         decalsystem->model = model;
11536
11537         RSurf_ActiveModelEntity(ent, true, false, false);
11538
11539         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11540         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11541         VectorNormalize(localnormal);
11542         localsize = worldsize*rsurface.inversematrixscale;
11543         localmins[0] = localorigin[0] - localsize;
11544         localmins[1] = localorigin[1] - localsize;
11545         localmins[2] = localorigin[2] - localsize;
11546         localmaxs[0] = localorigin[0] + localsize;
11547         localmaxs[1] = localorigin[1] + localsize;
11548         localmaxs[2] = localorigin[2] + localsize;
11549
11550         //VectorCopy(localnormal, planes[4]);
11551         //VectorVectors(planes[4], planes[2], planes[0]);
11552         AnglesFromVectors(angles, localnormal, NULL, false);
11553         AngleVectors(angles, planes[0], planes[2], planes[4]);
11554         VectorNegate(planes[0], planes[1]);
11555         VectorNegate(planes[2], planes[3]);
11556         VectorNegate(planes[4], planes[5]);
11557         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11558         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11559         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11560         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11561         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11562         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11563
11564 #if 1
11565 // works
11566 {
11567         matrix4x4_t forwardprojection;
11568         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11569         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11570 }
11571 #else
11572 // broken
11573 {
11574         float projectionvector[4][3];
11575         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11576         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11577         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11578         projectionvector[0][0] = planes[0][0] * ilocalsize;
11579         projectionvector[0][1] = planes[1][0] * ilocalsize;
11580         projectionvector[0][2] = planes[2][0] * ilocalsize;
11581         projectionvector[1][0] = planes[0][1] * ilocalsize;
11582         projectionvector[1][1] = planes[1][1] * ilocalsize;
11583         projectionvector[1][2] = planes[2][1] * ilocalsize;
11584         projectionvector[2][0] = planes[0][2] * ilocalsize;
11585         projectionvector[2][1] = planes[1][2] * ilocalsize;
11586         projectionvector[2][2] = planes[2][2] * ilocalsize;
11587         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11588         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11589         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11590         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11591 }
11592 #endif
11593
11594         dynamic = model->surfmesh.isanimated;
11595         numsurfacelist = model->nummodelsurfaces;
11596         surfacelist = model->sortedmodelsurfaces;
11597         surfaces = model->data_surfaces;
11598
11599         bih = NULL;
11600         bih_triangles_count = -1;
11601         if(!dynamic)
11602         {
11603                 if(model->render_bih.numleafs)
11604                         bih = &model->render_bih;
11605                 else if(model->collision_bih.numleafs)
11606                         bih = &model->collision_bih;
11607         }
11608         if(bih)
11609                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11610         if(bih_triangles_count == 0)
11611                 return;
11612         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11613                 return;
11614         if(bih_triangles_count > 0)
11615         {
11616                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11617                 {
11618                         surfaceindex = bih_surfaces[triangleindex];
11619                         surface = surfaces + surfaceindex;
11620                         texture = surface->texture;
11621                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11622                                 continue;
11623                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11624                                 continue;
11625                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11626                 }
11627         }
11628         else
11629         {
11630                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11631                 {
11632                         surfaceindex = surfacelist[surfacelistindex];
11633                         surface = surfaces + surfaceindex;
11634                         // check cull box first because it rejects more than any other check
11635                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11636                                 continue;
11637                         // skip transparent surfaces
11638                         texture = surface->texture;
11639                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11640                                 continue;
11641                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11642                                 continue;
11643                         numtriangles = surface->num_triangles;
11644                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11645                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11646                 }
11647         }
11648 }
11649
11650 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11651 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)
11652 {
11653         int renderentityindex;
11654         float worldmins[3];
11655         float worldmaxs[3];
11656         entity_render_t *ent;
11657
11658         if (!cl_decals_newsystem.integer)
11659                 return;
11660
11661         worldmins[0] = worldorigin[0] - worldsize;
11662         worldmins[1] = worldorigin[1] - worldsize;
11663         worldmins[2] = worldorigin[2] - worldsize;
11664         worldmaxs[0] = worldorigin[0] + worldsize;
11665         worldmaxs[1] = worldorigin[1] + worldsize;
11666         worldmaxs[2] = worldorigin[2] + worldsize;
11667
11668         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11669
11670         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11671         {
11672                 ent = r_refdef.scene.entities[renderentityindex];
11673                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11674                         continue;
11675
11676                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11677         }
11678 }
11679
11680 typedef struct r_decalsystem_splatqueue_s
11681 {
11682         vec3_t worldorigin;
11683         vec3_t worldnormal;
11684         float color[4];
11685         float tcrange[4];
11686         float worldsize;
11687         unsigned int decalsequence;
11688 }
11689 r_decalsystem_splatqueue_t;
11690
11691 int r_decalsystem_numqueued = 0;
11692 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11693
11694 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)
11695 {
11696         r_decalsystem_splatqueue_t *queue;
11697
11698         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11699                 return;
11700
11701         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11702         VectorCopy(worldorigin, queue->worldorigin);
11703         VectorCopy(worldnormal, queue->worldnormal);
11704         Vector4Set(queue->color, r, g, b, a);
11705         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11706         queue->worldsize = worldsize;
11707         queue->decalsequence = cl.decalsequence++;
11708 }
11709
11710 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11711 {
11712         int i;
11713         r_decalsystem_splatqueue_t *queue;
11714
11715         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11716                 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);
11717         r_decalsystem_numqueued = 0;
11718 }
11719
11720 extern cvar_t cl_decals_max;
11721 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11722 {
11723         int i;
11724         decalsystem_t *decalsystem = &ent->decalsystem;
11725         int numdecals;
11726         unsigned int killsequence;
11727         tridecal_t *decal;
11728         float frametime;
11729         float lifetime;
11730
11731         if (!decalsystem->numdecals)
11732                 return;
11733
11734         if (r_showsurfaces.integer)
11735                 return;
11736
11737         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11738         {
11739                 R_DecalSystem_Reset(decalsystem);
11740                 return;
11741         }
11742
11743         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11744         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11745
11746         if (decalsystem->lastupdatetime)
11747                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11748         else
11749                 frametime = 0;
11750         decalsystem->lastupdatetime = r_refdef.scene.time;
11751         numdecals = decalsystem->numdecals;
11752
11753         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11754         {
11755                 if (decal->color4f[0][3])
11756                 {
11757                         decal->lived += frametime;
11758                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11759                         {
11760                                 memset(decal, 0, sizeof(*decal));
11761                                 if (decalsystem->freedecal > i)
11762                                         decalsystem->freedecal = i;
11763                         }
11764                 }
11765         }
11766         decal = decalsystem->decals;
11767         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11768                 numdecals--;
11769
11770         // collapse the array by shuffling the tail decals into the gaps
11771         for (;;)
11772         {
11773                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11774                         decalsystem->freedecal++;
11775                 if (decalsystem->freedecal == numdecals)
11776                         break;
11777                 decal[decalsystem->freedecal] = decal[--numdecals];
11778         }
11779
11780         decalsystem->numdecals = numdecals;
11781
11782         if (numdecals <= 0)
11783         {
11784                 // if there are no decals left, reset decalsystem
11785                 R_DecalSystem_Reset(decalsystem);
11786         }
11787 }
11788
11789 extern skinframe_t *decalskinframe;
11790 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11791 {
11792         int i;
11793         decalsystem_t *decalsystem = &ent->decalsystem;
11794         int numdecals;
11795         tridecal_t *decal;
11796         float faderate;
11797         float alpha;
11798         float *v3f;
11799         float *c4f;
11800         float *t2f;
11801         const int *e;
11802         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11803         int numtris = 0;
11804
11805         numdecals = decalsystem->numdecals;
11806         if (!numdecals)
11807                 return;
11808
11809         if (r_showsurfaces.integer)
11810                 return;
11811
11812         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11813         {
11814                 R_DecalSystem_Reset(decalsystem);
11815                 return;
11816         }
11817
11818         // if the model is static it doesn't matter what value we give for
11819         // wantnormals and wanttangents, so this logic uses only rules applicable
11820         // to a model, knowing that they are meaningless otherwise
11821         RSurf_ActiveModelEntity(ent, false, false, false);
11822
11823         decalsystem->lastupdatetime = r_refdef.scene.time;
11824
11825         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11826
11827         // update vertex positions for animated models
11828         v3f = decalsystem->vertex3f;
11829         c4f = decalsystem->color4f;
11830         t2f = decalsystem->texcoord2f;
11831         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11832         {
11833                 if (!decal->color4f[0][3])
11834                         continue;
11835
11836                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11837                         continue;
11838
11839                 // skip backfaces
11840                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11841                         continue;
11842
11843                 // update color values for fading decals
11844                 if (decal->lived >= cl_decals_time.value)
11845                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11846                 else
11847                         alpha = 1.0f;
11848
11849                 c4f[ 0] = decal->color4f[0][0] * alpha;
11850                 c4f[ 1] = decal->color4f[0][1] * alpha;
11851                 c4f[ 2] = decal->color4f[0][2] * alpha;
11852                 c4f[ 3] = 1;
11853                 c4f[ 4] = decal->color4f[1][0] * alpha;
11854                 c4f[ 5] = decal->color4f[1][1] * alpha;
11855                 c4f[ 6] = decal->color4f[1][2] * alpha;
11856                 c4f[ 7] = 1;
11857                 c4f[ 8] = decal->color4f[2][0] * alpha;
11858                 c4f[ 9] = decal->color4f[2][1] * alpha;
11859                 c4f[10] = decal->color4f[2][2] * alpha;
11860                 c4f[11] = 1;
11861
11862                 t2f[0] = decal->texcoord2f[0][0];
11863                 t2f[1] = decal->texcoord2f[0][1];
11864                 t2f[2] = decal->texcoord2f[1][0];
11865                 t2f[3] = decal->texcoord2f[1][1];
11866                 t2f[4] = decal->texcoord2f[2][0];
11867                 t2f[5] = decal->texcoord2f[2][1];
11868
11869                 // update vertex positions for animated models
11870                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11871                 {
11872                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11873                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11874                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11875                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11876                 }
11877                 else
11878                 {
11879                         VectorCopy(decal->vertex3f[0], v3f);
11880                         VectorCopy(decal->vertex3f[1], v3f + 3);
11881                         VectorCopy(decal->vertex3f[2], v3f + 6);
11882                 }
11883
11884                 if (r_refdef.fogenabled)
11885                 {
11886                         alpha = RSurf_FogVertex(v3f);
11887                         VectorScale(c4f, alpha, c4f);
11888                         alpha = RSurf_FogVertex(v3f + 3);
11889                         VectorScale(c4f + 4, alpha, c4f + 4);
11890                         alpha = RSurf_FogVertex(v3f + 6);
11891                         VectorScale(c4f + 8, alpha, c4f + 8);
11892                 }
11893
11894                 v3f += 9;
11895                 c4f += 12;
11896                 t2f += 6;
11897                 numtris++;
11898         }
11899
11900         if (numtris > 0)
11901         {
11902                 r_refdef.stats[r_stat_drawndecals] += numtris;
11903
11904                 // now render the decals all at once
11905                 // (this assumes they all use one particle font texture!)
11906                 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);
11907 //              R_Mesh_ResetTextureState();
11908                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11909                 GL_DepthMask(false);
11910                 GL_DepthRange(0, 1);
11911                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11912                 GL_DepthTest(true);
11913                 GL_CullFace(GL_NONE);
11914                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11915                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11916                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11917         }
11918 }
11919
11920 static void R_DrawModelDecals(void)
11921 {
11922         int i, numdecals;
11923
11924         // fade faster when there are too many decals
11925         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11926         for (i = 0;i < r_refdef.scene.numentities;i++)
11927                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11928
11929         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11930         for (i = 0;i < r_refdef.scene.numentities;i++)
11931                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11932                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11933
11934         R_DecalSystem_ApplySplatEntitiesQueue();
11935
11936         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11937         for (i = 0;i < r_refdef.scene.numentities;i++)
11938                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11939
11940         r_refdef.stats[r_stat_totaldecals] += numdecals;
11941
11942         if (r_showsurfaces.integer)
11943                 return;
11944
11945         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11946
11947         for (i = 0;i < r_refdef.scene.numentities;i++)
11948         {
11949                 if (!r_refdef.viewcache.entityvisible[i])
11950                         continue;
11951                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11952                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11953         }
11954 }
11955
11956 extern cvar_t mod_collision_bih;
11957 static void R_DrawDebugModel(void)
11958 {
11959         entity_render_t *ent = rsurface.entity;
11960         int i, j, flagsmask;
11961         const msurface_t *surface;
11962         dp_model_t *model = ent->model;
11963
11964         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11965                 return;
11966
11967         if (r_showoverdraw.value > 0)
11968         {
11969                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11970                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11971                 R_SetupShader_Generic_NoTexture(false, false);
11972                 GL_DepthTest(false);
11973                 GL_DepthMask(false);
11974                 GL_DepthRange(0, 1);
11975                 GL_BlendFunc(GL_ONE, GL_ONE);
11976                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11977                 {
11978                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11979                                 continue;
11980                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11981                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11982                         {
11983                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11984                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11985                                 if (!rsurface.texture->currentlayers->depthmask)
11986                                         GL_Color(c, 0, 0, 1.0f);
11987                                 else if (ent == r_refdef.scene.worldentity)
11988                                         GL_Color(c, c, c, 1.0f);
11989                                 else
11990                                         GL_Color(0, c, 0, 1.0f);
11991                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11992                                 RSurf_DrawBatch();
11993                         }
11994                 }
11995                 rsurface.texture = NULL;
11996         }
11997
11998         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11999
12000 //      R_Mesh_ResetTextureState();
12001         R_SetupShader_Generic_NoTexture(false, false);
12002         GL_DepthRange(0, 1);
12003         GL_DepthTest(!r_showdisabledepthtest.integer);
12004         GL_DepthMask(false);
12005         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12006
12007         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12008         {
12009                 int triangleindex;
12010                 int bihleafindex;
12011                 qboolean cullbox = false;
12012                 const q3mbrush_t *brush;
12013                 const bih_t *bih = &model->collision_bih;
12014                 const bih_leaf_t *bihleaf;
12015                 float vertex3f[3][3];
12016                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12017                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12018                 {
12019                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12020                                 continue;
12021                         switch (bihleaf->type)
12022                         {
12023                         case BIH_BRUSH:
12024                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12025                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12026                                 {
12027                                         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);
12028                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12029                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12030                                 }
12031                                 break;
12032                         case BIH_COLLISIONTRIANGLE:
12033                                 triangleindex = bihleaf->itemindex;
12034                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12035                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12036                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12037                                 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);
12038                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12039                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12040                                 break;
12041                         case BIH_RENDERTRIANGLE:
12042                                 triangleindex = bihleaf->itemindex;
12043                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12044                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12045                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12046                                 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);
12047                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12048                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12049                                 break;
12050                         }
12051                 }
12052         }
12053
12054         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12055
12056 #ifndef USE_GLES2
12057         if (r_showtris.value > 0 && qglPolygonMode)
12058         {
12059                 if (r_showdisabledepthtest.integer)
12060                 {
12061                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12062                         GL_DepthMask(false);
12063                 }
12064                 else
12065                 {
12066                         GL_BlendFunc(GL_ONE, GL_ZERO);
12067                         GL_DepthMask(true);
12068                 }
12069                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12070                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12071                 {
12072                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12073                                 continue;
12074                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12075                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12076                         {
12077                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12078                                 if (!rsurface.texture->currentlayers->depthmask)
12079                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12080                                 else if (ent == r_refdef.scene.worldentity)
12081                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12082                                 else
12083                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12084                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12085                                 RSurf_DrawBatch();
12086                         }
12087                 }
12088                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12089                 rsurface.texture = NULL;
12090         }
12091
12092         if (r_shownormals.value != 0 && qglBegin)
12093         {
12094                 int l, k;
12095                 vec3_t v;
12096                 if (r_showdisabledepthtest.integer)
12097                 {
12098                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12099                         GL_DepthMask(false);
12100                 }
12101                 else
12102                 {
12103                         GL_BlendFunc(GL_ONE, GL_ZERO);
12104                         GL_DepthMask(true);
12105                 }
12106                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12107                 {
12108                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12109                                 continue;
12110                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12111                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12112                         {
12113                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12114                                 qglBegin(GL_LINES);
12115                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12116                                 {
12117                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12118                                         {
12119                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12120                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12121                                                 qglVertex3f(v[0], v[1], v[2]);
12122                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + 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.batchsvector3f)
12128                                 {
12129                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12130                                         {
12131                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12132                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12133                                                 qglVertex3f(v[0], v[1], v[2]);
12134                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + 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.batchtvector3f)
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, r_refdef.view.colorscale, 0, 1);
12145                                                 qglVertex3f(v[0], v[1], v[2]);
12146                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + 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                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12152                                 {
12153                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12154                                         {
12155                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12156                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12157                                                 qglVertex3f(v[0], v[1], v[2]);
12158                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12159                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12160                                                 qglVertex3f(v[0], v[1], v[2]);
12161                                         }
12162                                 }
12163                                 qglEnd();
12164                                 CHECKGLERROR
12165                         }
12166                 }
12167                 rsurface.texture = NULL;
12168         }
12169 #endif
12170 }
12171
12172 int r_maxsurfacelist = 0;
12173 const msurface_t **r_surfacelist = NULL;
12174 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12175 {
12176         int i, j, endj, flagsmask;
12177         dp_model_t *model = ent->model;
12178         msurface_t *surfaces;
12179         unsigned char *update;
12180         int numsurfacelist = 0;
12181         if (model == NULL)
12182                 return;
12183
12184         if (r_maxsurfacelist < model->num_surfaces)
12185         {
12186                 r_maxsurfacelist = model->num_surfaces;
12187                 if (r_surfacelist)
12188                         Mem_Free((msurface_t **)r_surfacelist);
12189                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12190         }
12191
12192         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12193                 RSurf_ActiveModelEntity(ent, false, false, false);
12194         else if (prepass)
12195                 RSurf_ActiveModelEntity(ent, true, true, true);
12196         else if (depthonly)
12197         {
12198                 switch (vid.renderpath)
12199                 {
12200                 case RENDERPATH_GL20:
12201                 case RENDERPATH_D3D9:
12202                 case RENDERPATH_D3D10:
12203                 case RENDERPATH_D3D11:
12204                 case RENDERPATH_SOFT:
12205                 case RENDERPATH_GLES2:
12206                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12207                         break;
12208                 case RENDERPATH_GL11:
12209                 case RENDERPATH_GL13:
12210                 case RENDERPATH_GLES1:
12211                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12212                         break;
12213                 }
12214         }
12215         else
12216         {
12217                 switch (vid.renderpath)
12218                 {
12219                 case RENDERPATH_GL20:
12220                 case RENDERPATH_D3D9:
12221                 case RENDERPATH_D3D10:
12222                 case RENDERPATH_D3D11:
12223                 case RENDERPATH_SOFT:
12224                 case RENDERPATH_GLES2:
12225                         RSurf_ActiveModelEntity(ent, true, true, false);
12226                         break;
12227                 case RENDERPATH_GL11:
12228                 case RENDERPATH_GL13:
12229                 case RENDERPATH_GLES1:
12230                         RSurf_ActiveModelEntity(ent, true, false, false);
12231                         break;
12232                 }
12233         }
12234
12235         surfaces = model->data_surfaces;
12236         update = model->brushq1.lightmapupdateflags;
12237
12238         // update light styles
12239         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12240         {
12241                 model_brush_lightstyleinfo_t *style;
12242                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12243                 {
12244                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12245                         {
12246                                 int *list = style->surfacelist;
12247                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12248                                 for (j = 0;j < style->numsurfaces;j++)
12249                                         update[list[j]] = true;
12250                         }
12251                 }
12252         }
12253
12254         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12255
12256         if (debug)
12257         {
12258                 R_DrawDebugModel();
12259                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12260                 return;
12261         }
12262
12263         rsurface.lightmaptexture = NULL;
12264         rsurface.deluxemaptexture = NULL;
12265         rsurface.uselightmaptexture = false;
12266         rsurface.texture = NULL;
12267         rsurface.rtlight = NULL;
12268         numsurfacelist = 0;
12269         // add visible surfaces to draw list
12270         if (ent == r_refdef.scene.worldentity)
12271         {
12272                 // for the world entity, check surfacevisible
12273                 for (i = 0;i < model->nummodelsurfaces;i++)
12274                 {
12275                         j = model->sortedmodelsurfaces[i];
12276                         if (r_refdef.viewcache.world_surfacevisible[j])
12277                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12278                 }
12279         }
12280         else
12281         {
12282                 // add all surfaces
12283                 for (i = 0; i < model->nummodelsurfaces; i++)
12284                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12285         }
12286         // don't do anything if there were no surfaces
12287         if (!numsurfacelist)
12288         {
12289                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12290                 return;
12291         }
12292         // update lightmaps if needed
12293         if (update)
12294         {
12295                 int updated = 0;
12296                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12297                 {
12298                         if (update[j])
12299                         {
12300                                 updated++;
12301                                 R_BuildLightMap(ent, surfaces + j);
12302                         }
12303                 }
12304         }
12305
12306         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12307
12308         // add to stats if desired
12309         if (r_speeds.integer && !skysurfaces && !depthonly)
12310         {
12311                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12312                 for (j = 0;j < numsurfacelist;j++)
12313                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12314         }
12315
12316         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12317 }
12318
12319 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12320 {
12321         int q;
12322         static texture_t texture;
12323         static msurface_t surface;
12324         const msurface_t *surfacelist = &surface;
12325
12326         // fake enough texture and surface state to render this geometry
12327
12328         texture.update_lastrenderframe = -1; // regenerate this texture
12329         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12330         texture.basealpha = 1.0f;
12331         texture.currentskinframe = skinframe;
12332         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12333         texture.offsetmapping = OFFSETMAPPING_OFF;
12334         texture.offsetscale = 1;
12335         texture.specularscalemod = 1;
12336         texture.specularpowermod = 1;
12337         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12338         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12339         // JUST GREP FOR "specularscalemod = 1".
12340
12341         for (q = 0; q < 3; q++)
12342         {
12343                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12344                 texture.render_modellight_lightdir[q] = q == 2;
12345                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12346                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12347                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12348                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12349                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12350                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12351                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12352                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12353         }
12354         texture.currentalpha = 1.0f;
12355
12356         surface.texture = &texture;
12357         surface.num_triangles = numtriangles;
12358         surface.num_firsttriangle = firsttriangle;
12359         surface.num_vertices = numvertices;
12360         surface.num_firstvertex = firstvertex;
12361
12362         // now render it
12363         rsurface.texture = R_GetCurrentTexture(surface.texture);
12364         rsurface.lightmaptexture = NULL;
12365         rsurface.deluxemaptexture = NULL;
12366         rsurface.uselightmaptexture = false;
12367         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12368 }
12369
12370 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)
12371 {
12372         static msurface_t surface;
12373         const msurface_t *surfacelist = &surface;
12374
12375         // fake enough texture and surface state to render this geometry
12376         surface.texture = texture;
12377         surface.num_triangles = numtriangles;
12378         surface.num_firsttriangle = firsttriangle;
12379         surface.num_vertices = numvertices;
12380         surface.num_firstvertex = firstvertex;
12381
12382         // now render it
12383         rsurface.texture = R_GetCurrentTexture(surface.texture);
12384         rsurface.lightmaptexture = NULL;
12385         rsurface.deluxemaptexture = NULL;
12386         rsurface.uselightmaptexture = false;
12387         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12388 }