]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
CSQC polygonbegin functionality now uses the CL_MeshEntities system, this finally...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
83
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
97 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
104 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
105 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
115 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
122
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
126
127 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
131 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
132
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
144 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
147 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
158 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
159
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
168
169 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
170 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
171
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
175
176 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
177 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
178 cvar_t r_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"};
179 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
180 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
181 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"};
182 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)"};
183 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)"};
184 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
185
186 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
187 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)"};
188 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
189 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)"};
190 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
191 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)"};
192 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)"};
193 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
194 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"};
195 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."};
196 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
197 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)"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205
206 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)"};
207 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)"};
208 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
209 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"};
210 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
211 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
212 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
213 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"};
214 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"};
215 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
216
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
221
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
224
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
231
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
242
243 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
244
245 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
246
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
248
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
250
251 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
252 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
255
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
258
259 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
260
261 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
263 {
264         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
268 };
269
270 extern cvar_t v_glslgamma_2d;
271
272 extern qboolean v_flipped_state;
273
274 r_framebufferstate_t r_fb;
275
276 /// shadow volume bsp struct with automatically growing nodes buffer
277 svbsp_t r_svbsp;
278
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
280
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
294
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
297 {
298         char basename[64];
299         rtexture_t *texture;
300 }
301 cubemapinfo_t;
302
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
305
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
309
310 typedef struct r_qwskincache_s
311 {
312         char name[MAX_QPATH];
313         skinframe_t *skinframe;
314 }
315 r_qwskincache_t;
316
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
319
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 extern const float r_d3dscreenvertex3f[12];
323 const float r_screenvertex3f[12] =
324 {
325         0, 0, 0,
326         1, 0, 0,
327         1, 1, 0,
328         0, 1, 0
329 };
330 const float r_d3dscreenvertex3f[12] =
331 {
332         0, 1, 0,
333         1, 1, 0,
334         1, 0, 0,
335         0, 0, 0
336 };
337
338 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
339 {
340         int i;
341         for (i = 0;i < verts;i++)
342         {
343                 out[0] = in[0] * r;
344                 out[1] = in[1] * g;
345                 out[2] = in[2] * b;
346                 out[3] = in[3];
347                 in += 4;
348                 out += 4;
349         }
350 }
351
352 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
353 {
354         int i;
355         for (i = 0;i < verts;i++)
356         {
357                 out[0] = r;
358                 out[1] = g;
359                 out[2] = b;
360                 out[3] = a;
361                 out += 4;
362         }
363 }
364
365 // FIXME: move this to client?
366 void FOG_clear(void)
367 {
368         if (gamemode == GAME_NEHAHRA)
369         {
370                 Cvar_Set("gl_fogenable", "0");
371                 Cvar_Set("gl_fogdensity", "0.2");
372                 Cvar_Set("gl_fogred", "0.3");
373                 Cvar_Set("gl_foggreen", "0.3");
374                 Cvar_Set("gl_fogblue", "0.3");
375         }
376         r_refdef.fog_density = 0;
377         r_refdef.fog_red = 0;
378         r_refdef.fog_green = 0;
379         r_refdef.fog_blue = 0;
380         r_refdef.fog_alpha = 1;
381         r_refdef.fog_start = 0;
382         r_refdef.fog_end = 16384;
383         r_refdef.fog_height = 1<<30;
384         r_refdef.fog_fadedepth = 128;
385         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
386 }
387
388 static void R_BuildBlankTextures(void)
389 {
390         unsigned char data[4];
391         data[2] = 128; // normal X
392         data[1] = 128; // normal Y
393         data[0] = 255; // normal Z
394         data[3] = 255; // height
395         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396         data[0] = 255;
397         data[1] = 255;
398         data[2] = 255;
399         data[3] = 255;
400         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401         data[0] = 128;
402         data[1] = 128;
403         data[2] = 128;
404         data[3] = 255;
405         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406         data[0] = 0;
407         data[1] = 0;
408         data[2] = 0;
409         data[3] = 255;
410         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
411 }
412
413 static void R_BuildNoTexture(void)
414 {
415         int x, y;
416         unsigned char pix[16][16][4];
417         // this makes a light grey/dark grey checkerboard texture
418         for (y = 0;y < 16;y++)
419         {
420                 for (x = 0;x < 16;x++)
421                 {
422                         if ((y < 8) ^ (x < 8))
423                         {
424                                 pix[y][x][0] = 128;
425                                 pix[y][x][1] = 128;
426                                 pix[y][x][2] = 128;
427                                 pix[y][x][3] = 255;
428                         }
429                         else
430                         {
431                                 pix[y][x][0] = 64;
432                                 pix[y][x][1] = 64;
433                                 pix[y][x][2] = 64;
434                                 pix[y][x][3] = 255;
435                         }
436                 }
437         }
438         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
439 }
440
441 static void R_BuildWhiteCube(void)
442 {
443         unsigned char data[6*1*1*4];
444         memset(data, 255, sizeof(data));
445         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446 }
447
448 static void R_BuildNormalizationCube(void)
449 {
450         int x, y, side;
451         vec3_t v;
452         vec_t s, t, intensity;
453 #define NORMSIZE 64
454         unsigned char *data;
455         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
456         for (side = 0;side < 6;side++)
457         {
458                 for (y = 0;y < NORMSIZE;y++)
459                 {
460                         for (x = 0;x < NORMSIZE;x++)
461                         {
462                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
463                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464                                 switch(side)
465                                 {
466                                 default:
467                                 case 0:
468                                         v[0] = 1;
469                                         v[1] = -t;
470                                         v[2] = -s;
471                                         break;
472                                 case 1:
473                                         v[0] = -1;
474                                         v[1] = -t;
475                                         v[2] = s;
476                                         break;
477                                 case 2:
478                                         v[0] = s;
479                                         v[1] = 1;
480                                         v[2] = t;
481                                         break;
482                                 case 3:
483                                         v[0] = s;
484                                         v[1] = -1;
485                                         v[2] = -t;
486                                         break;
487                                 case 4:
488                                         v[0] = s;
489                                         v[1] = -t;
490                                         v[2] = 1;
491                                         break;
492                                 case 5:
493                                         v[0] = -s;
494                                         v[1] = -t;
495                                         v[2] = -1;
496                                         break;
497                                 }
498                                 intensity = 127.0f / sqrt(DotProduct(v, v));
499                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
500                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
501                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
502                                 data[((side*64+y)*64+x)*4+3] = 255;
503                         }
504                 }
505         }
506         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
507         Mem_Free(data);
508 }
509
510 static void R_BuildFogTexture(void)
511 {
512         int x, b;
513 #define FOGWIDTH 256
514         unsigned char data1[FOGWIDTH][4];
515         //unsigned char data2[FOGWIDTH][4];
516         double d, r, alpha;
517
518         r_refdef.fogmasktable_start = r_refdef.fog_start;
519         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
520         r_refdef.fogmasktable_range = r_refdef.fogrange;
521         r_refdef.fogmasktable_density = r_refdef.fog_density;
522
523         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
524         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
525         {
526                 d = (x * r - r_refdef.fogmasktable_start);
527                 if(developer_extra.integer)
528                         Con_DPrintf("%f ", d);
529                 d = max(0, d);
530                 if (r_fog_exp2.integer)
531                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
532                 else
533                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
534                 if(developer_extra.integer)
535                         Con_DPrintf(" : %f ", alpha);
536                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
537                 if(developer_extra.integer)
538                         Con_DPrintf(" = %f\n", alpha);
539                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
540         }
541
542         for (x = 0;x < FOGWIDTH;x++)
543         {
544                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
545                 data1[x][0] = b;
546                 data1[x][1] = b;
547                 data1[x][2] = b;
548                 data1[x][3] = 255;
549                 //data2[x][0] = 255 - b;
550                 //data2[x][1] = 255 - b;
551                 //data2[x][2] = 255 - b;
552                 //data2[x][3] = 255;
553         }
554         if (r_texture_fogattenuation)
555         {
556                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558         }
559         else
560         {
561                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
562                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
563         }
564 }
565
566 static void R_BuildFogHeightTexture(void)
567 {
568         unsigned char *inpixels;
569         int size;
570         int x;
571         int y;
572         int j;
573         float c[4];
574         float f;
575         inpixels = NULL;
576         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
577         if (r_refdef.fogheighttexturename[0])
578                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
579         if (!inpixels)
580         {
581                 r_refdef.fog_height_tablesize = 0;
582                 if (r_texture_fogheighttexture)
583                         R_FreeTexture(r_texture_fogheighttexture);
584                 r_texture_fogheighttexture = NULL;
585                 if (r_refdef.fog_height_table2d)
586                         Mem_Free(r_refdef.fog_height_table2d);
587                 r_refdef.fog_height_table2d = NULL;
588                 if (r_refdef.fog_height_table1d)
589                         Mem_Free(r_refdef.fog_height_table1d);
590                 r_refdef.fog_height_table1d = NULL;
591                 return;
592         }
593         size = image_width;
594         r_refdef.fog_height_tablesize = size;
595         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
596         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
597         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
598         Mem_Free(inpixels);
599         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
600         // average fog color table accounting for every fog layer between a point
601         // and the camera.  (Note: attenuation is handled separately!)
602         for (y = 0;y < size;y++)
603         {
604                 for (x = 0;x < size;x++)
605                 {
606                         Vector4Clear(c);
607                         f = 0;
608                         if (x < y)
609                         {
610                                 for (j = x;j <= y;j++)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         else
617                         {
618                                 for (j = x;j >= y;j--)
619                                 {
620                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
621                                         f++;
622                                 }
623                         }
624                         f = 1.0f / f;
625                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
626                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
627                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
629                 }
630         }
631         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
632 }
633
634 //=======================================================================================================================================================
635
636 static const char *builtinshaderstrings[] =
637 {
638 #include "shader_glsl.h"
639 0
640 };
641
642 const char *builtinhlslshaderstrings[] =
643 {
644 #include "shader_hlsl.h"
645 0
646 };
647
648 //=======================================================================================================================================================
649
650 typedef struct shaderpermutationinfo_s
651 {
652         const char *pretext;
653         const char *name;
654 }
655 shaderpermutationinfo_t;
656
657 typedef struct shadermodeinfo_s
658 {
659         const char *sourcebasename;
660         const char *extension;
661         const char **builtinshaderstrings;
662         const char *pretext;
663         const char *name;
664         char *filename;
665         char *builtinstring;
666         int builtincrc;
667 }
668 shadermodeinfo_t;
669
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
672 {
673         {"#define USEDIFFUSE\n", " diffuse"},
674         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
675         {"#define USEVIEWTINT\n", " viewtint"},
676         {"#define USECOLORMAPPING\n", " colormapping"},
677         {"#define USESATURATION\n", " saturation"},
678         {"#define USEFOGINSIDE\n", " foginside"},
679         {"#define USEFOGOUTSIDE\n", " fogoutside"},
680         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
681         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
682         {"#define USEGAMMARAMPS\n", " gammaramps"},
683         {"#define USECUBEFILTER\n", " cubefilter"},
684         {"#define USEGLOW\n", " glow"},
685         {"#define USEBLOOM\n", " bloom"},
686         {"#define USESPECULAR\n", " specular"},
687         {"#define USEPOSTPROCESSING\n", " postprocessing"},
688         {"#define USEREFLECTION\n", " reflection"},
689         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
690         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
691         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
692         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
693         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
694         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
695         {"#define USEALPHAKILL\n", " alphakill"},
696         {"#define USEREFLECTCUBE\n", " reflectcube"},
697         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
698         {"#define USEBOUNCEGRID\n", " bouncegrid"},
699         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
700         {"#define USETRIPPY\n", " trippy"},
701         {"#define USEDEPTHRGB\n", " depthrgb"},
702         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
703         {"#define USESKELETAL\n", " skeletal"},
704         {"#define USEOCCLUDE\n", " occlude"}
705 };
706
707 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
708 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
709 {
710         // SHADERLANGUAGE_GLSL
711         {
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729         },
730         // SHADERLANGUAGE_HLSL
731         {
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
749         },
750 };
751
752 struct r_glsl_permutation_s;
753 typedef struct r_glsl_permutation_s
754 {
755         /// hash lookup data
756         struct r_glsl_permutation_s *hashnext;
757         unsigned int mode;
758         dpuint64 permutation;
759
760         /// indicates if we have tried compiling this permutation already
761         qboolean compiled;
762         /// 0 if compilation failed
763         int program;
764         // texture units assigned to each detected uniform
765         int tex_Texture_First;
766         int tex_Texture_Second;
767         int tex_Texture_GammaRamps;
768         int tex_Texture_Normal;
769         int tex_Texture_Color;
770         int tex_Texture_Gloss;
771         int tex_Texture_Glow;
772         int tex_Texture_SecondaryNormal;
773         int tex_Texture_SecondaryColor;
774         int tex_Texture_SecondaryGloss;
775         int tex_Texture_SecondaryGlow;
776         int tex_Texture_Pants;
777         int tex_Texture_Shirt;
778         int tex_Texture_FogHeightTexture;
779         int tex_Texture_FogMask;
780         int tex_Texture_Lightmap;
781         int tex_Texture_Deluxemap;
782         int tex_Texture_Attenuation;
783         int tex_Texture_Cube;
784         int tex_Texture_Refraction;
785         int tex_Texture_Reflection;
786         int tex_Texture_ShadowMap2D;
787         int tex_Texture_CubeProjection;
788         int tex_Texture_ScreenNormalMap;
789         int tex_Texture_ScreenDiffuse;
790         int tex_Texture_ScreenSpecular;
791         int tex_Texture_ReflectMask;
792         int tex_Texture_ReflectCube;
793         int tex_Texture_BounceGrid;
794         /// locations of detected uniforms in program object, or -1 if not found
795         int loc_Texture_First;
796         int loc_Texture_Second;
797         int loc_Texture_GammaRamps;
798         int loc_Texture_Normal;
799         int loc_Texture_Color;
800         int loc_Texture_Gloss;
801         int loc_Texture_Glow;
802         int loc_Texture_SecondaryNormal;
803         int loc_Texture_SecondaryColor;
804         int loc_Texture_SecondaryGloss;
805         int loc_Texture_SecondaryGlow;
806         int loc_Texture_Pants;
807         int loc_Texture_Shirt;
808         int loc_Texture_FogHeightTexture;
809         int loc_Texture_FogMask;
810         int loc_Texture_Lightmap;
811         int loc_Texture_Deluxemap;
812         int loc_Texture_Attenuation;
813         int loc_Texture_Cube;
814         int loc_Texture_Refraction;
815         int loc_Texture_Reflection;
816         int loc_Texture_ShadowMap2D;
817         int loc_Texture_CubeProjection;
818         int loc_Texture_ScreenNormalMap;
819         int loc_Texture_ScreenDiffuse;
820         int loc_Texture_ScreenSpecular;
821         int loc_Texture_ReflectMask;
822         int loc_Texture_ReflectCube;
823         int loc_Texture_BounceGrid;
824         int loc_Alpha;
825         int loc_BloomBlur_Parameters;
826         int loc_ClientTime;
827         int loc_Color_Ambient;
828         int loc_Color_Diffuse;
829         int loc_Color_Specular;
830         int loc_Color_Glow;
831         int loc_Color_Pants;
832         int loc_Color_Shirt;
833         int loc_DeferredColor_Ambient;
834         int loc_DeferredColor_Diffuse;
835         int loc_DeferredColor_Specular;
836         int loc_DeferredMod_Diffuse;
837         int loc_DeferredMod_Specular;
838         int loc_DistortScaleRefractReflect;
839         int loc_EyePosition;
840         int loc_FogColor;
841         int loc_FogHeightFade;
842         int loc_FogPlane;
843         int loc_FogPlaneViewDist;
844         int loc_FogRangeRecip;
845         int loc_LightColor;
846         int loc_LightDir;
847         int loc_LightPosition;
848         int loc_OffsetMapping_ScaleSteps;
849         int loc_OffsetMapping_LodDistance;
850         int loc_OffsetMapping_Bias;
851         int loc_PixelSize;
852         int loc_ReflectColor;
853         int loc_ReflectFactor;
854         int loc_ReflectOffset;
855         int loc_RefractColor;
856         int loc_Saturation;
857         int loc_ScreenCenterRefractReflect;
858         int loc_ScreenScaleRefractReflect;
859         int loc_ScreenToDepth;
860         int loc_ShadowMap_Parameters;
861         int loc_ShadowMap_TextureScale;
862         int loc_SpecularPower;
863         int loc_Skeletal_Transform12;
864         int loc_UserVec1;
865         int loc_UserVec2;
866         int loc_UserVec3;
867         int loc_UserVec4;
868         int loc_ViewTintColor;
869         int loc_ViewToLight;
870         int loc_ModelToLight;
871         int loc_TexMatrix;
872         int loc_BackgroundTexMatrix;
873         int loc_ModelViewProjectionMatrix;
874         int loc_ModelViewMatrix;
875         int loc_PixelToScreenTexCoord;
876         int loc_ModelToReflectCube;
877         int loc_ShadowMapMatrix;
878         int loc_BloomColorSubtract;
879         int loc_NormalmapScrollBlend;
880         int loc_BounceGridMatrix;
881         int loc_BounceGridIntensity;
882         /// uniform block bindings
883         int ubibind_Skeletal_Transform12_UniformBlock;
884         /// uniform block indices
885         int ubiloc_Skeletal_Transform12_UniformBlock;
886 }
887 r_glsl_permutation_t;
888
889 #define SHADERPERMUTATION_HASHSIZE 256
890
891
892 // non-degradable "lightweight" shader parameters to keep the permutations simpler
893 // these can NOT degrade! only use for simple stuff
894 enum
895 {
896         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
897         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
898         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
899         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
900         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
902         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
903         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
904         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
905         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
906         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
907         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
908         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
909         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
910 };
911 #define SHADERSTATICPARMS_COUNT 14
912
913 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
914 static int shaderstaticparms_count = 0;
915
916 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
917 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
918
919 extern qboolean r_shadow_shadowmapsampler;
920 extern int r_shadow_shadowmappcf;
921 qboolean R_CompileShader_CheckStaticParms(void)
922 {
923         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
924         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
925         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
926
927         // detect all
928         if (r_glsl_saturation_redcompensate.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
930         if (r_glsl_vertextextureblend_usebothalphas.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
932         if (r_shadow_glossexact.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
934         if (r_glsl_postprocess.integer)
935         {
936                 if (r_glsl_postprocess_uservec1_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
938                 if (r_glsl_postprocess_uservec2_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
940                 if (r_glsl_postprocess_uservec3_enable.integer)
941                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
942                 if (r_glsl_postprocess_uservec4_enable.integer)
943                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
944         }
945         if (r_fxaa.integer)
946                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
947         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
949
950         if (r_shadow_shadowmapsampler)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
952         if (r_shadow_shadowmappcf > 1)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
954         else if (r_shadow_shadowmappcf)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
956         if (r_celshading.integer)
957                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
958         if (r_celoutlines.integer)
959                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
960
961         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
962 }
963
964 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
965         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
966                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
967         else \
968                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
969 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
970 {
971         shaderstaticparms_count = 0;
972
973         // emit all
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
988 }
989
990 /// information about each possible shader permutation
991 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
992 /// currently selected permutation
993 r_glsl_permutation_t *r_glsl_permutation;
994 /// storage for permutations linked in the hash table
995 memexpandablearray_t r_glsl_permutationarray;
996
997 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
998 {
999         //unsigned int hashdepth = 0;
1000         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1001         r_glsl_permutation_t *p;
1002         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1003         {
1004                 if (p->mode == mode && p->permutation == permutation)
1005                 {
1006                         //if (hashdepth > 10)
1007                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1008                         return p;
1009                 }
1010                 //hashdepth++;
1011         }
1012         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1013         p->mode = mode;
1014         p->permutation = permutation;
1015         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1016         r_glsl_permutationhash[mode][hashindex] = p;
1017         //if (hashdepth > 10)
1018         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1019         return p;
1020 }
1021
1022 static char *R_ShaderStrCat(const char **strings)
1023 {
1024         char *string, *s;
1025         const char **p = strings;
1026         const char *t;
1027         size_t len = 0;
1028         for (p = strings;(t = *p);p++)
1029                 len += strlen(t);
1030         len++;
1031         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1032         len = 0;
1033         for (p = strings;(t = *p);p++)
1034         {
1035                 len = strlen(t);
1036                 memcpy(s, t, len);
1037                 s += len;
1038         }
1039         *s = 0;
1040         return string;
1041 }
1042
1043 static char *R_ShaderStrCat(const char **strings);
1044 static void R_InitShaderModeInfo(void)
1045 {
1046         int i, language;
1047         shadermodeinfo_t *modeinfo;
1048         // 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)
1049         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1050         {
1051                 for (i = 0; i < SHADERMODE_COUNT; i++)
1052                 {
1053                         char filename[MAX_QPATH];
1054                         modeinfo = &shadermodeinfo[language][i];
1055                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1056                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1057                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1058                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1059                 }
1060         }
1061 }
1062
1063 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1064 {
1065         char *shaderstring;
1066         // if the mode has no filename we have to return the builtin string
1067         if (builtinonly || !modeinfo->filename)
1068                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1069         // note that FS_LoadFile appends a 0 byte to make it a valid string
1070         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1071         if (shaderstring)
1072         {
1073                 if (printfromdisknotice)
1074                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1075                 return shaderstring;
1076         }
1077         // fall back to builtinstring
1078         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1079 }
1080
1081 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1082 {
1083         int i;
1084         int ubibind;
1085         int sampler;
1086         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1087         char *sourcestring;
1088         char permutationname[256];
1089         int vertstrings_count = 0;
1090         int geomstrings_count = 0;
1091         int fragstrings_count = 0;
1092         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095
1096         if (p->compiled)
1097                 return;
1098         p->compiled = true;
1099         p->program = 0;
1100
1101         permutationname[0] = 0;
1102         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1103
1104         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1105
1106         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1107         if(vid.support.glshaderversion >= 140)
1108         {
1109                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1110                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1111                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1112                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1113                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1114                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1115         }
1116         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1117         else if(vid.support.glshaderversion >= 130)
1118         {
1119                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1120                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1121                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1122                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1123                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1124                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1125         }
1126         // if we can do #version 120, we should (this adds the invariant keyword)
1127         else if(vid.support.glshaderversion >= 120)
1128         {
1129                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1130                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1131                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1132                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1133                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1134                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1135         }
1136         // GLES also adds several things from GLSL120
1137         switch(vid.renderpath)
1138         {
1139         case RENDERPATH_GLES2:
1140                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1141                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1142                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1143                 break;
1144         default:
1145                 break;
1146         }
1147
1148         // the first pretext is which type of shader to compile as
1149         // (later these will all be bound together as a program object)
1150         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1151         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1152         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1153
1154         // the second pretext is the mode (for example a light source)
1155         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1156         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1157         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1158         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1159
1160         // now add all the permutation pretexts
1161         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1162         {
1163                 if (permutation & (1ll<<i))
1164                 {
1165                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1166                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1167                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1169                 }
1170                 else
1171                 {
1172                         // keep line numbers correct
1173                         vertstrings_list[vertstrings_count++] = "\n";
1174                         geomstrings_list[geomstrings_count++] = "\n";
1175                         fragstrings_list[fragstrings_count++] = "\n";
1176                 }
1177         }
1178
1179         // add static parms
1180         R_CompileShader_AddStaticParms(mode, permutation);
1181         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182         vertstrings_count += shaderstaticparms_count;
1183         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184         geomstrings_count += shaderstaticparms_count;
1185         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186         fragstrings_count += shaderstaticparms_count;
1187
1188         // now append the shader text itself
1189         vertstrings_list[vertstrings_count++] = sourcestring;
1190         geomstrings_list[geomstrings_count++] = sourcestring;
1191         fragstrings_list[fragstrings_count++] = sourcestring;
1192
1193         // compile the shader program
1194         if (vertstrings_count + geomstrings_count + fragstrings_count)
1195                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1196         if (p->program)
1197         {
1198                 CHECKGLERROR
1199                 qglUseProgram(p->program);CHECKGLERROR
1200                 // look up all the uniform variable names we care about, so we don't
1201                 // have to look them up every time we set them
1202
1203 #if 0
1204                 // debugging aid
1205                 {
1206                         GLint activeuniformindex = 0;
1207                         GLint numactiveuniforms = 0;
1208                         char uniformname[128];
1209                         GLsizei uniformnamelength = 0;
1210                         GLint uniformsize = 0;
1211                         GLenum uniformtype = 0;
1212                         memset(uniformname, 0, sizeof(uniformname));
1213                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1214                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1215                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1216                         {
1217                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1218                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1219                         }
1220                 }
1221 #endif
1222
1223                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1224                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1225                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1226                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1227                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1228                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1229                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1230                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1231                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1232                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1233                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1234                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1235                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1236                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1237                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1238                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1239                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1240                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1241                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1242                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1243                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1244                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1245                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1246                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1247                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1248                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1249                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1250                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1251                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1252                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1253                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1254                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1255                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1256                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1257                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1258                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1259                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1260                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1261                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1262                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1263                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1264                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1265                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1266                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1267                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1268                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1269                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1270                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1271                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1272                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1273                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1274                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1275                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1276                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1277                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1278                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1279                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1280                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1281                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1282                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1283                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1284                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1285                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1286                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1287                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1288                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1289                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1290                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1291                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1292                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1293                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1294                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1295                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1296                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1297                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1298                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1299                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1300                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1301                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1302                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1303                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1304                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1305                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1306                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1307                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1308                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1309                 // initialize the samplers to refer to the texture units we use
1310                 p->tex_Texture_First = -1;
1311                 p->tex_Texture_Second = -1;
1312                 p->tex_Texture_GammaRamps = -1;
1313                 p->tex_Texture_Normal = -1;
1314                 p->tex_Texture_Color = -1;
1315                 p->tex_Texture_Gloss = -1;
1316                 p->tex_Texture_Glow = -1;
1317                 p->tex_Texture_SecondaryNormal = -1;
1318                 p->tex_Texture_SecondaryColor = -1;
1319                 p->tex_Texture_SecondaryGloss = -1;
1320                 p->tex_Texture_SecondaryGlow = -1;
1321                 p->tex_Texture_Pants = -1;
1322                 p->tex_Texture_Shirt = -1;
1323                 p->tex_Texture_FogHeightTexture = -1;
1324                 p->tex_Texture_FogMask = -1;
1325                 p->tex_Texture_Lightmap = -1;
1326                 p->tex_Texture_Deluxemap = -1;
1327                 p->tex_Texture_Attenuation = -1;
1328                 p->tex_Texture_Cube = -1;
1329                 p->tex_Texture_Refraction = -1;
1330                 p->tex_Texture_Reflection = -1;
1331                 p->tex_Texture_ShadowMap2D = -1;
1332                 p->tex_Texture_CubeProjection = -1;
1333                 p->tex_Texture_ScreenNormalMap = -1;
1334                 p->tex_Texture_ScreenDiffuse = -1;
1335                 p->tex_Texture_ScreenSpecular = -1;
1336                 p->tex_Texture_ReflectMask = -1;
1337                 p->tex_Texture_ReflectCube = -1;
1338                 p->tex_Texture_BounceGrid = -1;
1339                 // bind the texture samplers in use
1340                 sampler = 0;
1341                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1342                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1343                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1344                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1345                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1346                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1347                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1348                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1349                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1352                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1353                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1354                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1355                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1356                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1357                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1358                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1359                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1360                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1361                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1362                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1363                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1364                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1365                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1367                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1368                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1369                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1370                 // get the uniform block indices so we can bind them
1371 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1372                 if (vid.support.arb_uniform_buffer_object)
1373                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1374                 else
1375 #endif
1376                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1377                 // clear the uniform block bindings
1378                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1379                 // bind the uniform blocks in use
1380                 ubibind = 0;
1381 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1382                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1383 #endif
1384                 // we're done compiling and setting up the shader, at least until it is used
1385                 CHECKGLERROR
1386                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1387         }
1388         else
1389                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1390
1391         // free the strings
1392         if (sourcestring)
1393                 Mem_Free(sourcestring);
1394 }
1395
1396 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1397 {
1398         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1399         if (r_glsl_permutation != perm)
1400         {
1401                 r_glsl_permutation = perm;
1402                 if (!r_glsl_permutation->program)
1403                 {
1404                         if (!r_glsl_permutation->compiled)
1405                         {
1406                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1407                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1408                         }
1409                         if (!r_glsl_permutation->program)
1410                         {
1411                                 // remove features until we find a valid permutation
1412                                 int i;
1413                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1414                                 {
1415                                         // reduce i more quickly whenever it would not remove any bits
1416                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1417                                         if (!(permutation & j))
1418                                                 continue;
1419                                         permutation -= j;
1420                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1421                                         if (!r_glsl_permutation->compiled)
1422                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1423                                         if (r_glsl_permutation->program)
1424                                                 break;
1425                                 }
1426                                 if (i >= SHADERPERMUTATION_COUNT)
1427                                 {
1428                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1429                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1430                                         qglUseProgram(0);CHECKGLERROR
1431                                         return; // no bit left to clear, entire mode is broken
1432                                 }
1433                         }
1434                 }
1435                 CHECKGLERROR
1436                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1437         }
1438         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1439         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1440         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1441         CHECKGLERROR
1442 }
1443
1444 #ifdef SUPPORTD3D
1445
1446 #ifdef SUPPORTD3D
1447 #include <d3d9.h>
1448 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1449 extern D3DCAPS9 vid_d3d9caps;
1450 #endif
1451
1452 struct r_hlsl_permutation_s;
1453 typedef struct r_hlsl_permutation_s
1454 {
1455         /// hash lookup data
1456         struct r_hlsl_permutation_s *hashnext;
1457         unsigned int mode;
1458         dpuint64 permutation;
1459
1460         /// indicates if we have tried compiling this permutation already
1461         qboolean compiled;
1462         /// NULL if compilation failed
1463         IDirect3DVertexShader9 *vertexshader;
1464         IDirect3DPixelShader9 *pixelshader;
1465 }
1466 r_hlsl_permutation_t;
1467
1468 typedef enum D3DVSREGISTER_e
1469 {
1470         D3DVSREGISTER_TexMatrix = 0, // float4x4
1471         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1472         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1473         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1474         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1475         D3DVSREGISTER_ModelToLight = 20, // float4x4
1476         D3DVSREGISTER_EyePosition = 24,
1477         D3DVSREGISTER_FogPlane = 25,
1478         D3DVSREGISTER_LightDir = 26,
1479         D3DVSREGISTER_LightPosition = 27,
1480 }
1481 D3DVSREGISTER_t;
1482
1483 typedef enum D3DPSREGISTER_e
1484 {
1485         D3DPSREGISTER_Alpha = 0,
1486         D3DPSREGISTER_BloomBlur_Parameters = 1,
1487         D3DPSREGISTER_ClientTime = 2,
1488         D3DPSREGISTER_Color_Ambient = 3,
1489         D3DPSREGISTER_Color_Diffuse = 4,
1490         D3DPSREGISTER_Color_Specular = 5,
1491         D3DPSREGISTER_Color_Glow = 6,
1492         D3DPSREGISTER_Color_Pants = 7,
1493         D3DPSREGISTER_Color_Shirt = 8,
1494         D3DPSREGISTER_DeferredColor_Ambient = 9,
1495         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1496         D3DPSREGISTER_DeferredColor_Specular = 11,
1497         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1498         D3DPSREGISTER_DeferredMod_Specular = 13,
1499         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1500         D3DPSREGISTER_EyePosition = 15, // unused
1501         D3DPSREGISTER_FogColor = 16,
1502         D3DPSREGISTER_FogHeightFade = 17,
1503         D3DPSREGISTER_FogPlane = 18,
1504         D3DPSREGISTER_FogPlaneViewDist = 19,
1505         D3DPSREGISTER_FogRangeRecip = 20,
1506         D3DPSREGISTER_LightColor = 21,
1507         D3DPSREGISTER_LightDir = 22, // unused
1508         D3DPSREGISTER_LightPosition = 23,
1509         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1510         D3DPSREGISTER_PixelSize = 25,
1511         D3DPSREGISTER_ReflectColor = 26,
1512         D3DPSREGISTER_ReflectFactor = 27,
1513         D3DPSREGISTER_ReflectOffset = 28,
1514         D3DPSREGISTER_RefractColor = 29,
1515         D3DPSREGISTER_Saturation = 30,
1516         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1517         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1518         D3DPSREGISTER_ScreenToDepth = 33,
1519         D3DPSREGISTER_ShadowMap_Parameters = 34,
1520         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1521         D3DPSREGISTER_SpecularPower = 36,
1522         D3DPSREGISTER_UserVec1 = 37,
1523         D3DPSREGISTER_UserVec2 = 38,
1524         D3DPSREGISTER_UserVec3 = 39,
1525         D3DPSREGISTER_UserVec4 = 40,
1526         D3DPSREGISTER_ViewTintColor = 41,
1527         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1528         D3DPSREGISTER_BloomColorSubtract = 43,
1529         D3DPSREGISTER_ViewToLight = 44, // float4x4
1530         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1531         D3DPSREGISTER_NormalmapScrollBlend = 52,
1532         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1533         D3DPSREGISTER_OffsetMapping_Bias = 54,
1534         // next at 54
1535 }
1536 D3DPSREGISTER_t;
1537
1538 /// information about each possible shader permutation
1539 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1540 /// currently selected permutation
1541 r_hlsl_permutation_t *r_hlsl_permutation;
1542 /// storage for permutations linked in the hash table
1543 memexpandablearray_t r_hlsl_permutationarray;
1544
1545 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1546 {
1547         //unsigned int hashdepth = 0;
1548         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1549         r_hlsl_permutation_t *p;
1550         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1551         {
1552                 if (p->mode == mode && p->permutation == permutation)
1553                 {
1554                         //if (hashdepth > 10)
1555                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1556                         return p;
1557                 }
1558                 //hashdepth++;
1559         }
1560         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1561         p->mode = mode;
1562         p->permutation = permutation;
1563         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1564         r_hlsl_permutationhash[mode][hashindex] = p;
1565         //if (hashdepth > 10)
1566         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1567         return p;
1568 }
1569
1570 #include <d3dx9.h>
1571 //#include <d3dx9shader.h>
1572 //#include <d3dx9mesh.h>
1573
1574 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1575 {
1576         DWORD *vsbin = NULL;
1577         DWORD *psbin = NULL;
1578         fs_offset_t vsbinsize;
1579         fs_offset_t psbinsize;
1580 //      IDirect3DVertexShader9 *vs = NULL;
1581 //      IDirect3DPixelShader9 *ps = NULL;
1582         ID3DXBuffer *vslog = NULL;
1583         ID3DXBuffer *vsbuffer = NULL;
1584         ID3DXConstantTable *vsconstanttable = NULL;
1585         ID3DXBuffer *pslog = NULL;
1586         ID3DXBuffer *psbuffer = NULL;
1587         ID3DXConstantTable *psconstanttable = NULL;
1588         int vsresult = 0;
1589         int psresult = 0;
1590         char temp[MAX_INPUTLINE];
1591         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1592         char vabuf[1024];
1593         qboolean debugshader = gl_paranoid.integer != 0;
1594         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1595         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596         if (!debugshader)
1597         {
1598                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1599                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1600         }
1601         if ((!vsbin && vertstring) || (!psbin && fragstring))
1602         {
1603                 const char* dllnames_d3dx9 [] =
1604                 {
1605                         "d3dx9_43.dll",
1606                         "d3dx9_42.dll",
1607                         "d3dx9_41.dll",
1608                         "d3dx9_40.dll",
1609                         "d3dx9_39.dll",
1610                         "d3dx9_38.dll",
1611                         "d3dx9_37.dll",
1612                         "d3dx9_36.dll",
1613                         "d3dx9_35.dll",
1614                         "d3dx9_34.dll",
1615                         "d3dx9_33.dll",
1616                         "d3dx9_32.dll",
1617                         "d3dx9_31.dll",
1618                         "d3dx9_30.dll",
1619                         "d3dx9_29.dll",
1620                         "d3dx9_28.dll",
1621                         "d3dx9_27.dll",
1622                         "d3dx9_26.dll",
1623                         "d3dx9_25.dll",
1624                         "d3dx9_24.dll",
1625                         NULL
1626                 };
1627                 dllhandle_t d3dx9_dll = NULL;
1628                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1629                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1630                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631                 dllfunction_t d3dx9_dllfuncs[] =
1632                 {
1633                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1634                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1635                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1636                         {NULL, NULL}
1637                 };
1638                 // 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...
1639 #ifndef ID3DXBuffer_GetBufferPointer
1640 #if !defined(__cplusplus) || defined(CINTERFACE)
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1643 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1644 #else
1645 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1646 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1647 #define ID3DXBuffer_Release(p)            (p)->Release()
1648 #endif
1649 #endif
1650                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1651                 {
1652                         DWORD shaderflags = 0;
1653                         if (debugshader)
1654                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1655                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1656                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1657                         if (vertstring && vertstring[0])
1658                         {
1659                                 if (debugshader)
1660                                 {
1661                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1662                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1663                                 }
1664                                 else
1665                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1666                                 if (vsbuffer)
1667                                 {
1668                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1669                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1670                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1671                                         ID3DXBuffer_Release(vsbuffer);
1672                                 }
1673                                 if (vslog)
1674                                 {
1675                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1676                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1677                                         ID3DXBuffer_Release(vslog);
1678                                 }
1679                         }
1680                         if (fragstring && fragstring[0])
1681                         {
1682                                 if (debugshader)
1683                                 {
1684                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1685                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1686                                 }
1687                                 else
1688                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1689                                 if (psbuffer)
1690                                 {
1691                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1692                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1693                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1694                                         ID3DXBuffer_Release(psbuffer);
1695                                 }
1696                                 if (pslog)
1697                                 {
1698                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1699                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1700                                         ID3DXBuffer_Release(pslog);
1701                                 }
1702                         }
1703                         Sys_UnloadLibrary(&d3dx9_dll);
1704                 }
1705                 else
1706                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1707         }
1708         if (vsbin && psbin)
1709         {
1710                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1711                 if (FAILED(vsresult))
1712                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1713                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1714                 if (FAILED(psresult))
1715                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1716         }
1717         // free the shader data
1718         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1719         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1720 }
1721
1722 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1723 {
1724         int i;
1725         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1726         int vertstring_length = 0;
1727         int geomstring_length = 0;
1728         int fragstring_length = 0;
1729         char *t;
1730         char *sourcestring;
1731         char *vertstring, *geomstring, *fragstring;
1732         char permutationname[256];
1733         char cachename[256];
1734         int vertstrings_count = 0;
1735         int geomstrings_count = 0;
1736         int fragstrings_count = 0;
1737         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1738         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740
1741         if (p->compiled)
1742                 return;
1743         p->compiled = true;
1744         p->vertexshader = NULL;
1745         p->pixelshader = NULL;
1746
1747         permutationname[0] = 0;
1748         cachename[0] = 0;
1749         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1750
1751         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1752         strlcat(cachename, "hlsl/", sizeof(cachename));
1753
1754         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1755         vertstrings_count = 0;
1756         geomstrings_count = 0;
1757         fragstrings_count = 0;
1758         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1759         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1760         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1761
1762         // the first pretext is which type of shader to compile as
1763         // (later these will all be bound together as a program object)
1764         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1765         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1766         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1767
1768         // the second pretext is the mode (for example a light source)
1769         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1770         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1771         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1772         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1773         strlcat(cachename, modeinfo->name, sizeof(cachename));
1774
1775         // now add all the permutation pretexts
1776         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777         {
1778                 if (permutation & (1ll<<i))
1779                 {
1780                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1781                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1782                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1784                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1785                 }
1786                 else
1787                 {
1788                         // keep line numbers correct
1789                         vertstrings_list[vertstrings_count++] = "\n";
1790                         geomstrings_list[geomstrings_count++] = "\n";
1791                         fragstrings_list[fragstrings_count++] = "\n";
1792                 }
1793         }
1794
1795         // add static parms
1796         R_CompileShader_AddStaticParms(mode, permutation);
1797         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798         vertstrings_count += shaderstaticparms_count;
1799         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800         geomstrings_count += shaderstaticparms_count;
1801         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802         fragstrings_count += shaderstaticparms_count;
1803
1804         // replace spaces in the cachename with _ characters
1805         for (i = 0;cachename[i];i++)
1806                 if (cachename[i] == ' ')
1807                         cachename[i] = '_';
1808
1809         // now append the shader text itself
1810         vertstrings_list[vertstrings_count++] = sourcestring;
1811         geomstrings_list[geomstrings_count++] = sourcestring;
1812         fragstrings_list[fragstrings_count++] = sourcestring;
1813
1814         vertstring_length = 0;
1815         for (i = 0;i < vertstrings_count;i++)
1816                 vertstring_length += (int)strlen(vertstrings_list[i]);
1817         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1818         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1819                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1820
1821         geomstring_length = 0;
1822         for (i = 0;i < geomstrings_count;i++)
1823                 geomstring_length += (int)strlen(geomstrings_list[i]);
1824         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1825         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1826                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1827
1828         fragstring_length = 0;
1829         for (i = 0;i < fragstrings_count;i++)
1830                 fragstring_length += (int)strlen(fragstrings_list[i]);
1831         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1832         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1833                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1834
1835         // try to load the cached shader, or generate one
1836         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1837
1838         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1839                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1840         else
1841                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1842
1843         // free the strings
1844         if (vertstring)
1845                 Mem_Free(vertstring);
1846         if (geomstring)
1847                 Mem_Free(geomstring);
1848         if (fragstring)
1849                 Mem_Free(fragstring);
1850         if (sourcestring)
1851                 Mem_Free(sourcestring);
1852 }
1853
1854 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1855 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1856 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);}
1857 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);}
1858 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);}
1859 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);}
1860
1861 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1862 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1863 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);}
1864 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);}
1865 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);}
1866 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);}
1867
1868 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1869 {
1870         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1871         if (r_hlsl_permutation != perm)
1872         {
1873                 r_hlsl_permutation = perm;
1874                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875                 {
1876                         if (!r_hlsl_permutation->compiled)
1877                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1878                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1879                         {
1880                                 // remove features until we find a valid permutation
1881                                 int i;
1882                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                                 {
1884                                         // reduce i more quickly whenever it would not remove any bits
1885                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1886                                         if (!(permutation & j))
1887                                                 continue;
1888                                         permutation -= j;
1889                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1890                                         if (!r_hlsl_permutation->compiled)
1891                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1892                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1893                                                 break;
1894                                 }
1895                                 if (i >= SHADERPERMUTATION_COUNT)
1896                                 {
1897                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1898                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1899                                         return; // no bit left to clear, entire mode is broken
1900                                 }
1901                         }
1902                 }
1903                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1904                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1905         }
1906         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1907         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1908         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1909 }
1910 #endif
1911
1912 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1913 {
1914         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1915         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1916         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1917         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1918 }
1919
1920 void R_GLSL_Restart_f(void)
1921 {
1922         unsigned int i, limit;
1923         switch(vid.renderpath)
1924         {
1925         case RENDERPATH_D3D9:
1926 #ifdef SUPPORTD3D
1927                 {
1928                         r_hlsl_permutation_t *p;
1929                         r_hlsl_permutation = NULL;
1930                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1931                         for (i = 0;i < limit;i++)
1932                         {
1933                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1934                                 {
1935                                         if (p->vertexshader)
1936                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1937                                         if (p->pixelshader)
1938                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1939                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1940                                 }
1941                         }
1942                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1943                 }
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 {
1955                         r_glsl_permutation_t *p;
1956                         r_glsl_permutation = NULL;
1957                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1958                         for (i = 0;i < limit;i++)
1959                         {
1960                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1961                                 {
1962                                         GL_Backend_FreeProgram(p->program);
1963                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1964                                 }
1965                         }
1966                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1967                 }
1968                 break;
1969         case RENDERPATH_GL11:
1970         case RENDERPATH_GL13:
1971         case RENDERPATH_GLES1:
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 break;
1975         }
1976 }
1977
1978 static void R_GLSL_DumpShader_f(void)
1979 {
1980         int i, language, mode, dupe;
1981         char *text;
1982         shadermodeinfo_t *modeinfo;
1983         qfile_t *file;
1984
1985         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1986         {
1987                 modeinfo = shadermodeinfo[language];
1988                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1989                 {
1990                         // don't dump the same file multiple times (most or all shaders come from the same file)
1991                         for (dupe = mode - 1;dupe >= 0;dupe--)
1992                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1993                                         break;
1994                         if (dupe >= 0)
1995                                 continue;
1996                         text = modeinfo[mode].builtinstring;
1997                         if (!text)
1998                                 continue;
1999                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2000                         if (file)
2001                         {
2002                                 FS_Print(file, "/* The engine may define the following macros:\n");
2003                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2004                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2005                                         FS_Print(file, modeinfo[i].pretext);
2006                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2007                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2008                                 FS_Print(file, "*/\n");
2009                                 FS_Print(file, text);
2010                                 FS_Close(file);
2011                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2012                         }
2013                         else
2014                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2015                 }
2016         }
2017 }
2018
2019 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2020 {
2021         dpuint64 permutation = 0;
2022         if (r_trippy.integer && !notrippy)
2023                 permutation |= SHADERPERMUTATION_TRIPPY;
2024         permutation |= SHADERPERMUTATION_VIEWTINT;
2025         if (first)
2026                 permutation |= SHADERPERMUTATION_DIFFUSE;
2027         if (second)
2028                 permutation |= SHADERPERMUTATION_SPECULAR;
2029         if (texturemode == GL_MODULATE)
2030                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2031         else if (texturemode == GL_ADD)
2032                 permutation |= SHADERPERMUTATION_GLOW;
2033         else if (texturemode == GL_DECAL)
2034                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2035         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2036                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2037         if (suppresstexalpha)
2038                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2039         if (!second)
2040                 texturemode = GL_MODULATE;
2041         if (vid.allowalphatocoverage)
2042                 GL_AlphaToCoverage(false);
2043         switch (vid.renderpath)
2044         {
2045         case RENDERPATH_D3D9:
2046 #ifdef SUPPORTD3D
2047                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2048                 R_Mesh_TexBind(GL20TU_FIRST , first );
2049                 R_Mesh_TexBind(GL20TU_SECOND, second);
2050                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2051                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2052 #endif
2053                 break;
2054         case RENDERPATH_D3D10:
2055                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056                 break;
2057         case RENDERPATH_D3D11:
2058                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059                 break;
2060         case RENDERPATH_GL20:
2061         case RENDERPATH_GLES2:
2062                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2063                 if (r_glsl_permutation->tex_Texture_First >= 0)
2064                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2065                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2066                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2067                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2068                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2069                 break;
2070         case RENDERPATH_GL13:
2071         case RENDERPATH_GLES1:
2072                 R_Mesh_TexBind(0, first );
2073                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2074                 R_Mesh_TexMatrix(0, NULL);
2075                 R_Mesh_TexBind(1, second);
2076                 if (second)
2077                 {
2078                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2079                         R_Mesh_TexMatrix(1, NULL);
2080                 }
2081                 break;
2082         case RENDERPATH_GL11:
2083                 R_Mesh_TexBind(0, first );
2084                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2085                 R_Mesh_TexMatrix(0, NULL);
2086                 break;
2087         case RENDERPATH_SOFT:
2088                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2089                 R_Mesh_TexBind(GL20TU_FIRST , first );
2090                 R_Mesh_TexBind(GL20TU_SECOND, second);
2091                 break;
2092         }
2093 }
2094
2095 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2096 {
2097         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2098 }
2099
2100 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2101 {
2102         dpuint64 permutation = 0;
2103         if (r_trippy.integer && !notrippy)
2104                 permutation |= SHADERPERMUTATION_TRIPPY;
2105         if (depthrgb)
2106                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2107         if (skeletal)
2108                 permutation |= SHADERPERMUTATION_SKELETAL;
2109
2110         if (vid.allowalphatocoverage)
2111                 GL_AlphaToCoverage(false);
2112         switch (vid.renderpath)
2113         {
2114         case RENDERPATH_D3D9:
2115 #ifdef SUPPORTD3D
2116                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2117 #endif
2118                 break;
2119         case RENDERPATH_D3D10:
2120                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2121                 break;
2122         case RENDERPATH_D3D11:
2123                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2124                 break;
2125         case RENDERPATH_GL20:
2126         case RENDERPATH_GLES2:
2127                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2128 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2129                 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);
2130 #endif
2131                 break;
2132         case RENDERPATH_GL13:
2133         case RENDERPATH_GLES1:
2134                 R_Mesh_TexBind(0, 0);
2135                 R_Mesh_TexBind(1, 0);
2136                 break;
2137         case RENDERPATH_GL11:
2138                 R_Mesh_TexBind(0, 0);
2139                 break;
2140         case RENDERPATH_SOFT:
2141                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2142                 break;
2143         }
2144 }
2145
2146 extern qboolean r_shadow_usingdeferredprepass;
2147 extern rtexture_t *r_shadow_attenuationgradienttexture;
2148 extern rtexture_t *r_shadow_attenuation2dtexture;
2149 extern rtexture_t *r_shadow_attenuation3dtexture;
2150 extern qboolean r_shadow_usingshadowmap2d;
2151 extern qboolean r_shadow_usingshadowmaportho;
2152 extern float r_shadow_modelshadowmap_texturescale[4];
2153 extern float r_shadow_modelshadowmap_parameters[4];
2154 extern float r_shadow_lightshadowmap_texturescale[4];
2155 extern float r_shadow_lightshadowmap_parameters[4];
2156 extern qboolean r_shadow_shadowmapvsdct;
2157 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2159 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2160 extern matrix4x4_t r_shadow_shadowmapmatrix;
2161 extern int r_shadow_prepass_width;
2162 extern int r_shadow_prepass_height;
2163 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2164 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2165 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2166 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2167
2168 #define BLENDFUNC_ALLOWS_COLORMOD      1
2169 #define BLENDFUNC_ALLOWS_FOG           2
2170 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2171 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2172 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2173 static int R_BlendFuncFlags(int src, int dst)
2174 {
2175         int r = 0;
2176
2177         // a blendfunc allows colormod if:
2178         // a) it can never keep the destination pixel invariant, or
2179         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2180         // this is to prevent unintended side effects from colormod
2181
2182         // a blendfunc allows fog if:
2183         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2184         // this is to prevent unintended side effects from fog
2185
2186         // these checks are the output of fogeval.pl
2187
2188         r |= BLENDFUNC_ALLOWS_COLORMOD;
2189         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2198         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2199         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2201         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2202         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2205         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2207         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2208         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2209         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2210
2211         return r;
2212 }
2213
2214 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)
2215 {
2216         // select a permutation of the lighting shader appropriate to this
2217         // combination of texture, entity, light source, and fogging, only use the
2218         // minimum features necessary to avoid wasting rendering time in the
2219         // fragment shader on features that are not being used
2220         dpuint64 permutation = 0;
2221         unsigned int mode = 0;
2222         int blendfuncflags;
2223         texture_t *t = rsurface.texture;
2224         float m16f[16];
2225         matrix4x4_t tempmatrix;
2226         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2227         if (r_trippy.integer && !notrippy)
2228                 permutation |= SHADERPERMUTATION_TRIPPY;
2229         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2230                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2231         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2232                 permutation |= SHADERPERMUTATION_OCCLUDE;
2233         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2234                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2235         if (rsurfacepass == RSURFPASS_BACKGROUND)
2236         {
2237                 // distorted background
2238                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2239                 {
2240                         mode = SHADERMODE_WATER;
2241                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2242                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2243                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2244                         {
2245                                 // this is the right thing to do for wateralpha
2246                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2247                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2248                         }
2249                         else
2250                         {
2251                                 // this is the right thing to do for entity alpha
2252                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254                         }
2255                 }
2256                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2257                 {
2258                         mode = SHADERMODE_REFRACTION;
2259                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2260                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2261                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263                 }
2264                 else
2265                 {
2266                         mode = SHADERMODE_GENERIC;
2267                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2268                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2269                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2270                 }
2271                 if (vid.allowalphatocoverage)
2272                         GL_AlphaToCoverage(false);
2273         }
2274         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2275         {
2276                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2277                 {
2278                         switch(t->offsetmapping)
2279                         {
2280                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283                         case OFFSETMAPPING_OFF: break;
2284                         }
2285                 }
2286                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288                 // normalmap (deferred prepass), may use alpha test on diffuse
2289                 mode = SHADERMODE_DEFERREDGEOMETRY;
2290                 GL_BlendFunc(GL_ONE, GL_ZERO);
2291                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2292                 if (vid.allowalphatocoverage)
2293                         GL_AlphaToCoverage(false);
2294         }
2295         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2296         {
2297                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2298                 {
2299                         switch(t->offsetmapping)
2300                         {
2301                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_OFF: break;
2305                         }
2306                 }
2307                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2310                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2311                 // light source
2312                 mode = SHADERMODE_LIGHTSOURCE;
2313                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2314                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2315                 if (VectorLength2(rtlightdiffuse) > 0)
2316                         permutation |= SHADERPERMUTATION_DIFFUSE;
2317                 if (VectorLength2(rtlightspecular) > 0)
2318                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2319                 if (r_refdef.fogenabled)
2320                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321                 if (t->colormapping)
2322                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2323                 if (r_shadow_usingshadowmap2d)
2324                 {
2325                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2326                         if(r_shadow_shadowmapvsdct)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2328
2329                         if (r_shadow_shadowmap2ddepthbuffer)
2330                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2331                 }
2332                 if (t->reflectmasktexture)
2333                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2335                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2336                 if (vid.allowalphatocoverage)
2337                         GL_AlphaToCoverage(false);
2338         }
2339         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2340         {
2341                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2342                 {
2343                         switch(t->offsetmapping)
2344                         {
2345                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2346                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_OFF: break;
2349                         }
2350                 }
2351                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2352                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2354                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2355                 // directional model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (VectorLength2(t->render_modellight_diffuse))
2360                         permutation |= SHADERPERMUTATION_DIFFUSE;
2361                 if (VectorLength2(t->render_modellight_specular) > 0)
2362                         permutation |= SHADERPERMUTATION_SPECULAR;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (t->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmap2ddepthbuffer)
2373                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374                 }
2375                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (t->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegrid_state.directional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2404                 {
2405                         switch(t->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2417                 // lightmapped wall
2418                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419                         permutation |= SHADERPERMUTATION_GLOW;
2420                 if (r_refdef.fogenabled)
2421                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422                 if (t->colormapping)
2423                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2424                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425                 {
2426                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428
2429                         if (r_shadow_shadowmap2ddepthbuffer)
2430                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2431                 }
2432                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433                         permutation |= SHADERPERMUTATION_REFLECTION;
2434                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2435                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436                 if (t->reflectmasktexture)
2437                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438                 if (FAKELIGHT_ENABLED)
2439                 {
2440                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441                         mode = SHADERMODE_FAKELIGHT;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (VectorLength2(t->render_lightmap_specular) > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447                 {
2448                         // deluxemapping (light direction texture)
2449                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451                         else
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (VectorLength2(t->render_lightmap_specular) > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 2)
2458                 {
2459                         // fake deluxemapping (uniform light direction in tangentspace)
2460                         if (rsurface.uselightmaptexture)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (VectorLength2(t->render_lightmap_specular) > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (rsurface.uselightmaptexture)
2469                 {
2470                         // ordinary lightmapping (q1bsp, q3bsp)
2471                         mode = SHADERMODE_LIGHTMAP;
2472                 }
2473                 else
2474                 {
2475                         // ordinary vertex coloring (q3bsp)
2476                         mode = SHADERMODE_VERTEXCOLOR;
2477                 }
2478                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2479                 {
2480                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481                         if (r_shadow_bouncegrid_state.directional)
2482                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483                 }
2484                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2485                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486                 // when using alphatocoverage, we don't need alphakill
2487                 if (vid.allowalphatocoverage)
2488                 {
2489                         if (r_transparent_alphatocoverage.integer)
2490                         {
2491                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493                         }
2494                         else
2495                                 GL_AlphaToCoverage(false);
2496                 }
2497         }
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502         switch(vid.renderpath)
2503         {
2504         case RENDERPATH_D3D9:
2505 #ifdef SUPPORTD3D
2506                 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);
2507                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2508                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510                 if (mode == SHADERMODE_LIGHTSOURCE)
2511                 {
2512                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2514                 }
2515                 else
2516                 {
2517                         if (mode == SHADERMODE_LIGHTDIRECTION)
2518                         {
2519                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2520                         }
2521                 }
2522                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2532                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2535
2536                         // additive passes are only darkened by fog, not tinted
2537                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2539                 }
2540                 else
2541                 {
2542                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2544                         if (mode == SHADERMODE_FLATCOLOR)
2545                         {
2546                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2547                         }
2548                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2555                         }
2556                         else
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2561                         }
2562                         // additive passes are only darkened by fog, not tinted
2563                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2565                         else
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2567                         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);
2568                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2572                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2573                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2575                         if (mode == SHADERMODE_WATER)
2576                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2577                 }
2578                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2579                 {
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2582                 }
2583                 else
2584                 {
2585                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2586                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2587                 }
2588                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2589                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2590                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2591                 if (t->pantstexture)
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2593                 else
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2595                 if (t->shirttexture)
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2597                 else
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2603                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2604                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2605                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2608                         );
2609                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2610                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2611                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2612                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2613
2614                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2615                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2616                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2617                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2622                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2624                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2626                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2627                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2628                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2629                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2630                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2631                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2632                 {
2633                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2634                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2635                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636                 }
2637                 else
2638                 {
2639                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2640                 }
2641 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2642                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2643                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2644                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2645                 {
2646                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2647                         if (rsurface.rtlight)
2648                         {
2649                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2650                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2651                         }
2652                 }
2653 #endif
2654                 break;
2655         case RENDERPATH_D3D10:
2656                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657                 break;
2658         case RENDERPATH_D3D11:
2659                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2660                 break;
2661         case RENDERPATH_GL20:
2662         case RENDERPATH_GLES2:
2663                 if (!vid.useinterleavedarrays)
2664                 {
2665                         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);
2666                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2667                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2674                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2675                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2676                 }
2677                 else
2678                 {
2679                         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);
2680                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2681                 }
2682                 // this has to be after RSurf_PrepareVerticesForBatch
2683                 if (rsurface.batchskeletaltransform3x4buffer)
2684                         permutation |= SHADERPERMUTATION_SKELETAL;
2685                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2687                 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);
2688 #endif
2689                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2690                 if (mode == SHADERMODE_LIGHTSOURCE)
2691                 {
2692                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2693                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2694                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2695                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2696                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2697                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2698         
2699                         // additive passes are only darkened by fog, not tinted
2700                         if (r_glsl_permutation->loc_FogColor >= 0)
2701                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2702                         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);
2703                 }
2704                 else
2705                 {
2706                         if (mode == SHADERMODE_FLATCOLOR)
2707                         {
2708                                 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]);
2709                         }
2710                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2711                         {
2712                                 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]);
2713                                 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]);
2714                                 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]);
2715                                 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]);
2716                                 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]);
2717                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2718                                 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]);
2719                         }
2720                         else
2721                         {
2722                                 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]);
2723                                 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]);
2724                                 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]);
2725                                 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]);
2726                                 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]);
2727                         }
2728                         // additive passes are only darkened by fog, not tinted
2729                         if (r_glsl_permutation->loc_FogColor >= 0)
2730                         {
2731                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2732                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2733                                 else
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2735                         }
2736                         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);
2737                         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]);
2738                         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]);
2739                         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);
2740                         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);
2741                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2742                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2743                         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);
2744                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2745                 }
2746                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2747                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2749                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2750                 {
2751                         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]);
2752                         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]);
2753                 }
2754                 else
2755                 {
2756                         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]);
2757                         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]);
2758                 }
2759
2760                 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]);
2761                 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));
2762                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2763                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2764                 {
2765                         if (t->pantstexture)
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2767                         else
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2769                 }
2770                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2771                 {
2772                         if (t->shirttexture)
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2774                         else
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2776                 }
2777                 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]);
2778                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2779                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2780                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2781                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2782                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2783                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2784                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2786                         );
2787                 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);
2788                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2789                 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]);
2790                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2791                 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);}
2792                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2793
2794                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2795                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2796                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2797                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2798                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2799                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2800                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2801                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2802                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2805                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2807                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2808                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2809                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2810                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2811                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2814                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2815                 {
2816                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2817                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2818                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2819                 }
2820                 else
2821                 {
2822                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2823                 }
2824                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2825                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2826                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2827                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2828                 {
2829                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2830                         if (rsurface.rtlight)
2831                         {
2832                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2833                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2834                         }
2835                 }
2836                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2837                 CHECKGLERROR
2838                 break;
2839         case RENDERPATH_GL11:
2840         case RENDERPATH_GL13:
2841         case RENDERPATH_GLES1:
2842                 break;
2843         case RENDERPATH_SOFT:
2844                 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);
2845                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2846                 R_SetupShader_SetPermutationSoft(mode, permutation);
2847                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2848                 if (mode == SHADERMODE_LIGHTSOURCE)
2849                 {
2850                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2856         
2857                         // additive passes are only darkened by fog, not tinted
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2859                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2860                 }
2861                 else
2862                 {
2863                         if (mode == SHADERMODE_FLATCOLOR)
2864                         {
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2866                         }
2867                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2874                         }
2875                         else
2876                         {
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2880                         }
2881                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2883                         // additive passes are only darkened by fog, not tinted
2884                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2886                         else
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2888                         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);
2889                         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]);
2890                         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]);
2891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2893                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2897                 }
2898                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2899                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2900                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2901                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2902                 {
2903                         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]);
2904                         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]);
2905                 }
2906                 else
2907                 {
2908                         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]);
2909                         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]);
2910                 }
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (t->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (t->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2935                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938                         );
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2945                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2946                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2947                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2956                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2962                 {
2963                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967                 else
2968                 {
2969                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975                 {
2976                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977                         if (rsurface.rtlight)
2978                         {
2979                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981                         }
2982                 }
2983                 break;
2984         }
2985 }
2986
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989         // select a permutation of the lighting shader appropriate to this
2990         // combination of texture, entity, light source, and fogging, only use the
2991         // minimum features necessary to avoid wasting rendering time in the
2992         // fragment shader on features that are not being used
2993         dpuint64 permutation = 0;
2994         unsigned int mode = 0;
2995         const float *lightcolorbase = rtlight->currentcolor;
2996         float ambientscale = rtlight->ambientscale;
2997         float diffusescale = rtlight->diffusescale;
2998         float specularscale = rtlight->specularscale;
2999         // this is the location of the light in view space
3000         vec3_t viewlightorigin;
3001         // this transforms from view space (camera) to light space (cubemap)
3002         matrix4x4_t viewtolight;
3003         matrix4x4_t lighttoview;
3004         float viewtolight16f[16];
3005         // light source
3006         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007         if (rtlight->currentcubemap != r_texture_whitecube)
3008                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009         if (diffusescale > 0)
3010                 permutation |= SHADERPERMUTATION_DIFFUSE;
3011         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013         if (r_shadow_usingshadowmap2d)
3014         {
3015                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016                 if (r_shadow_shadowmapvsdct)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018
3019                 if (r_shadow_shadowmap2ddepthbuffer)
3020                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3021         }
3022         if (vid.allowalphatocoverage)
3023                 GL_AlphaToCoverage(false);
3024         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3027         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028         switch(vid.renderpath)
3029         {
3030         case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3040                 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);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043
3044                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 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]);
3066                 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]);
3067                 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);
3068                 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]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         case RENDERPATH_GL11:
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GLES1:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 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]);
3089                 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]);
3090                 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);
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         }
3101 }
3102
3103 #define SKINFRAME_HASH 1024
3104
3105 typedef struct
3106 {
3107         unsigned int loadsequence; // incremented each level change
3108         memexpandablearray_t array;
3109         skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113
3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116         r_skinframe.loadsequence++;
3117         // wrap it without hitting zero
3118         if (r_skinframe.loadsequence >= 200)
3119                 r_skinframe.loadsequence = 1;
3120 }
3121
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124         if (!skinframe)
3125                 return;
3126         // mark the skinframe as used for the purging code
3127         skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129
3130 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3131 {
3132         if (s->merged == s->base)
3133                 s->merged = NULL;
3134         R_PurgeTexture(s->stain); s->stain = NULL;
3135         R_PurgeTexture(s->merged); s->merged = NULL;
3136         R_PurgeTexture(s->base); s->base = NULL;
3137         R_PurgeTexture(s->pants); s->pants = NULL;
3138         R_PurgeTexture(s->shirt); s->shirt = NULL;
3139         R_PurgeTexture(s->nmap); s->nmap = NULL;
3140         R_PurgeTexture(s->gloss); s->gloss = NULL;
3141         R_PurgeTexture(s->glow); s->glow = NULL;
3142         R_PurgeTexture(s->fog); s->fog = NULL;
3143         R_PurgeTexture(s->reflect); s->reflect = NULL;
3144         s->loadsequence = 0;
3145 }
3146
3147 void R_SkinFrame_Purge(void)
3148 {
3149         int i;
3150         skinframe_t *s;
3151         for (i = 0;i < SKINFRAME_HASH;i++)
3152         {
3153                 for (s = r_skinframe.hash[i];s;s = s->next)
3154                 {
3155                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3156                                 R_SkinFrame_PurgeSkinFrame(s);
3157                 }
3158         }
3159 }
3160
3161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3162         skinframe_t *item;
3163         char basename[MAX_QPATH];
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         if( last == NULL ) {
3168                 int hashindex;
3169                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170                 item = r_skinframe.hash[hashindex];
3171         } else {
3172                 item = last->next;
3173         }
3174
3175         // linearly search through the hash bucket
3176         for( ; item ; item = item->next ) {
3177                 if( !strcmp( item->basename, basename ) ) {
3178                         return item;
3179                 }
3180         }
3181         return NULL;
3182 }
3183
3184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3185 {
3186         skinframe_t *item;
3187         int hashindex;
3188         char basename[MAX_QPATH];
3189
3190         Image_StripImageExtension(name, basename, sizeof(basename));
3191
3192         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3193         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3194                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3195                         break;
3196
3197         if (!item)
3198         {
3199                 if (!add)
3200                         return NULL;
3201                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202                 memset(item, 0, sizeof(*item));
3203                 strlcpy(item->basename, basename, sizeof(item->basename));
3204                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if (textureflags & TEXF_FORCE_RELOAD)
3212         {
3213                 if (!add)
3214                         return NULL;
3215                 R_SkinFrame_PurgeSkinFrame(item);
3216         }
3217
3218         R_SkinFrame_MarkUsed(item);
3219         return item;
3220 }
3221
3222 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3223         { \
3224                 unsigned long long avgcolor[5], wsum; \
3225                 int pix, comp, w; \
3226                 avgcolor[0] = 0; \
3227                 avgcolor[1] = 0; \
3228                 avgcolor[2] = 0; \
3229                 avgcolor[3] = 0; \
3230                 avgcolor[4] = 0; \
3231                 wsum = 0; \
3232                 for(pix = 0; pix < cnt; ++pix) \
3233                 { \
3234                         w = 0; \
3235                         for(comp = 0; comp < 3; ++comp) \
3236                                 w += getpixel; \
3237                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3238                         { \
3239                                 ++wsum; \
3240                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3241                                 w = getpixel; \
3242                                 for(comp = 0; comp < 3; ++comp) \
3243                                         avgcolor[comp] += getpixel * w; \
3244                                 avgcolor[3] += w; \
3245                         } \
3246                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247                         avgcolor[4] += getpixel; \
3248                 } \
3249                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3250                         avgcolor[3] = 1; \
3251                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3252                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3253                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3254                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3255         }
3256
3257 extern cvar_t gl_picmip;
3258 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3259 {
3260         int j;
3261         unsigned char *pixels;
3262         unsigned char *bumppixels;
3263         unsigned char *basepixels = NULL;
3264         int basepixels_width = 0;
3265         int basepixels_height = 0;
3266         skinframe_t *skinframe;
3267         rtexture_t *ddsbase = NULL;
3268         qboolean ddshasalpha = false;
3269         float ddsavgcolor[4];
3270         char basename[MAX_QPATH];
3271         int miplevel = R_PicmipForFlags(textureflags);
3272         int savemiplevel = miplevel;
3273         int mymiplevel;
3274         char vabuf[1024];
3275
3276         if (cls.state == ca_dedicated)
3277                 return NULL;
3278
3279         // return an existing skinframe if already loaded
3280         // if loading of the first image fails, don't make a new skinframe as it
3281         // would cause all future lookups of this to be missing
3282         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3283         if (skinframe && skinframe->base)
3284                 return skinframe;
3285
3286         Image_StripImageExtension(name, basename, sizeof(basename));
3287
3288         // check for DDS texture file first
3289         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3290         {
3291                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3292                 if (basepixels == NULL && fallbacknotexture)
3293                         basepixels = Image_GenerateNoTexture();
3294                 if (basepixels == NULL)
3295                         return NULL;
3296         }
3297
3298         // FIXME handle miplevel
3299
3300         if (developer_loading.integer)
3301                 Con_Printf("loading skin \"%s\"\n", name);
3302
3303         // we've got some pixels to store, so really allocate this new texture now
3304         if (!skinframe)
3305                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3306         textureflags &= ~TEXF_FORCE_RELOAD;
3307         skinframe->stain = NULL;
3308         skinframe->merged = NULL;
3309         skinframe->base = NULL;
3310         skinframe->pants = NULL;
3311         skinframe->shirt = NULL;
3312         skinframe->nmap = NULL;
3313         skinframe->gloss = NULL;
3314         skinframe->glow = NULL;
3315         skinframe->fog = NULL;
3316         skinframe->reflect = NULL;
3317         skinframe->hasalpha = false;
3318         // we could store the q2animname here too
3319
3320         if (ddsbase)
3321         {
3322                 skinframe->base = ddsbase;
3323                 skinframe->hasalpha = ddshasalpha;
3324                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3325                 if (r_loadfog && skinframe->hasalpha)
3326                         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);
3327                 //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]);
3328         }
3329         else
3330         {
3331                 basepixels_width = image_width;
3332                 basepixels_height = image_height;
3333                 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);
3334                 if (textureflags & TEXF_ALPHA)
3335                 {
3336                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3337                         {
3338                                 if (basepixels[j] < 255)
3339                                 {
3340                                         skinframe->hasalpha = true;
3341                                         break;
3342                                 }
3343                         }
3344                         if (r_loadfog && skinframe->hasalpha)
3345                         {
3346                                 // has transparent pixels
3347                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3348                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3349                                 {
3350                                         pixels[j+0] = 255;
3351                                         pixels[j+1] = 255;
3352                                         pixels[j+2] = 255;
3353                                         pixels[j+3] = basepixels[j+3];
3354                                 }
3355                                 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);
3356                                 Mem_Free(pixels);
3357                         }
3358                 }
3359                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3360 #ifndef USE_GLES2
3361                 //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]);
3362                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3363                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3364                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3365                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3366 #endif
3367         }
3368
3369         if (r_loaddds)
3370         {
3371                 mymiplevel = savemiplevel;
3372                 if (r_loadnormalmap)
3373                         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);
3374                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3375                 if (r_loadgloss)
3376                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3377                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3379                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3380         }
3381
3382         // _norm is the name used by tenebrae and has been adopted as standard
3383         if (r_loadnormalmap && skinframe->nmap == NULL)
3384         {
3385                 mymiplevel = savemiplevel;
3386                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3387                 {
3388                         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);
3389                         Mem_Free(pixels);
3390                         pixels = NULL;
3391                 }
3392                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3393                 {
3394                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3395                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3396                         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);
3397                         Mem_Free(pixels);
3398                         Mem_Free(bumppixels);
3399                 }
3400                 else if (r_shadow_bumpscale_basetexture.value > 0)
3401                 {
3402                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3403                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3404                         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);
3405                         Mem_Free(pixels);
3406                 }
3407 #ifndef USE_GLES2
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3409                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410 #endif
3411         }
3412
3413         // _luma is supported only for tenebrae compatibility
3414         // _glow is the preferred name
3415         mymiplevel = savemiplevel;
3416         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))))
3417         {
3418                 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);
3419 #ifndef USE_GLES2
3420                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3421                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3422 #endif
3423                 Mem_Free(pixels);pixels = NULL;
3424         }
3425
3426         mymiplevel = savemiplevel;
3427         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3428         {
3429                 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);
3430 #ifndef USE_GLES2
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3432                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434                 Mem_Free(pixels);
3435                 pixels = NULL;
3436         }
3437
3438         mymiplevel = savemiplevel;
3439         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3440         {
3441                 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);
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3444                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3445 #endif
3446                 Mem_Free(pixels);
3447                 pixels = NULL;
3448         }
3449
3450         mymiplevel = savemiplevel;
3451         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3452         {
3453                 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);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3456                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3457 #endif
3458                 Mem_Free(pixels);
3459                 pixels = NULL;
3460         }
3461
3462         mymiplevel = savemiplevel;
3463         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3464         {
3465                 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);
3466 #ifndef USE_GLES2
3467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3468                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3469 #endif
3470                 Mem_Free(pixels);
3471                 pixels = NULL;
3472         }
3473
3474         if (basepixels)
3475                 Mem_Free(basepixels);
3476
3477         return skinframe;
3478 }
3479
3480 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3481 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3482 {
3483         int i;
3484         skinframe_t *skinframe;
3485         char vabuf[1024];
3486
3487         if (cls.state == ca_dedicated)
3488                 return NULL;
3489
3490         // if already loaded just return it, otherwise make a new skinframe
3491         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3492         if (skinframe->base)
3493                 return skinframe;
3494         textureflags &= ~TEXF_FORCE_RELOAD;
3495
3496         skinframe->stain = NULL;
3497         skinframe->merged = NULL;
3498         skinframe->base = NULL;
3499         skinframe->pants = NULL;
3500         skinframe->shirt = NULL;
3501         skinframe->nmap = NULL;
3502         skinframe->gloss = NULL;
3503         skinframe->glow = NULL;
3504         skinframe->fog = NULL;
3505         skinframe->reflect = NULL;
3506         skinframe->hasalpha = false;
3507
3508         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3509         if (!skindata)
3510                 return NULL;
3511
3512         if (developer_loading.integer)
3513                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3514
3515         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3516         {
3517                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518                 unsigned char *b = a + width * height * 4;
3519                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3520                 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);
3521                 Mem_Free(a);
3522         }
3523         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3524         if (textureflags & TEXF_ALPHA)
3525         {
3526                 for (i = 3;i < width * height * 4;i += 4)
3527                 {
3528                         if (skindata[i] < 255)
3529                         {
3530                                 skinframe->hasalpha = true;
3531                                 break;
3532                         }
3533                 }
3534                 if (r_loadfog && skinframe->hasalpha)
3535                 {
3536                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3537                         memcpy(fogpixels, skindata, width * height * 4);
3538                         for (i = 0;i < width * height * 4;i += 4)
3539                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3540                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3541                         Mem_Free(fogpixels);
3542                 }
3543         }
3544
3545         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3546         //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]);
3547
3548         return skinframe;
3549 }
3550
3551 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3552 {
3553         int i;
3554         int featuresmask;
3555         skinframe_t *skinframe;
3556
3557         if (cls.state == ca_dedicated)
3558                 return NULL;
3559
3560         // if already loaded just return it, otherwise make a new skinframe
3561         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562         if (skinframe->base)
3563                 return skinframe;
3564         //textureflags &= ~TEXF_FORCE_RELOAD;
3565
3566         skinframe->stain = NULL;
3567         skinframe->merged = NULL;
3568         skinframe->base = NULL;
3569         skinframe->pants = NULL;
3570         skinframe->shirt = NULL;
3571         skinframe->nmap = NULL;
3572         skinframe->gloss = NULL;
3573         skinframe->glow = NULL;
3574         skinframe->fog = NULL;
3575         skinframe->reflect = NULL;
3576         skinframe->hasalpha = false;
3577
3578         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579         if (!skindata)
3580                 return NULL;
3581
3582         if (developer_loading.integer)
3583                 Con_Printf("loading quake skin \"%s\"\n", name);
3584
3585         // 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)
3586         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3587         memcpy(skinframe->qpixels, skindata, width*height);
3588         skinframe->qwidth = width;
3589         skinframe->qheight = height;
3590
3591         featuresmask = 0;
3592         for (i = 0;i < width * height;i++)
3593                 featuresmask |= palette_featureflags[skindata[i]];
3594
3595         skinframe->hasalpha = false;
3596         // fence textures
3597         if (name[0] == '{')
3598                 skinframe->hasalpha = true;
3599         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3600         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3601         skinframe->qgeneratemerged = true;
3602         skinframe->qgeneratebase = skinframe->qhascolormapping;
3603         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3604
3605         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3606         //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]);
3607
3608         return skinframe;
3609 }
3610
3611 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3612 {
3613         int width;
3614         int height;
3615         unsigned char *skindata;
3616         char vabuf[1024];
3617
3618         if (!skinframe->qpixels)
3619                 return;
3620
3621         if (!skinframe->qhascolormapping)
3622                 colormapped = false;
3623
3624         if (colormapped)
3625         {
3626                 if (!skinframe->qgeneratebase)
3627                         return;
3628         }
3629         else
3630         {
3631                 if (!skinframe->qgeneratemerged)
3632                         return;
3633         }
3634
3635         width = skinframe->qwidth;
3636         height = skinframe->qheight;
3637         skindata = skinframe->qpixels;
3638
3639         if (skinframe->qgeneratenmap)
3640         {
3641                 unsigned char *a, *b;
3642                 skinframe->qgeneratenmap = false;
3643                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3644                 b = a + width * height * 4;
3645                 // use either a custom palette or the quake palette
3646                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3647                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3648                 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);
3649                 Mem_Free(a);
3650         }
3651
3652         if (skinframe->qgenerateglow)
3653         {
3654                 skinframe->qgenerateglow = false;
3655                 if (skinframe->hasalpha) // fence textures
3656                         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
3657                 else
3658                         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
3659         }
3660
3661         if (colormapped)
3662         {
3663                 skinframe->qgeneratebase = false;
3664                 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);
3665                 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);
3666                 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);
3667         }
3668         else
3669         {
3670                 skinframe->qgeneratemerged = false;
3671                 if (skinframe->hasalpha) // fence textures
3672                         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);
3673                 else
3674                         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);
3675         }
3676
3677         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3678         {
3679                 Mem_Free(skinframe->qpixels);
3680                 skinframe->qpixels = NULL;
3681         }
3682 }
3683
3684 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)
3685 {
3686         int i;
3687         skinframe_t *skinframe;
3688         char vabuf[1024];
3689
3690         if (cls.state == ca_dedicated)
3691                 return NULL;
3692
3693         // if already loaded just return it, otherwise make a new skinframe
3694         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3695         if (skinframe->base)
3696                 return skinframe;
3697         textureflags &= ~TEXF_FORCE_RELOAD;
3698
3699         skinframe->stain = NULL;
3700         skinframe->merged = NULL;
3701         skinframe->base = NULL;
3702         skinframe->pants = NULL;
3703         skinframe->shirt = NULL;
3704         skinframe->nmap = NULL;
3705         skinframe->gloss = NULL;
3706         skinframe->glow = NULL;
3707         skinframe->fog = NULL;
3708         skinframe->reflect = NULL;
3709         skinframe->hasalpha = false;
3710
3711         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3712         if (!skindata)
3713                 return NULL;
3714
3715         if (developer_loading.integer)
3716                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3717
3718         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3719         if ((textureflags & TEXF_ALPHA) && alphapalette)
3720         {
3721                 for (i = 0;i < width * height;i++)
3722                 {
3723                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3724                         {
3725                                 skinframe->hasalpha = true;
3726                                 break;
3727                         }
3728                 }
3729                 if (r_loadfog && skinframe->hasalpha)
3730                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3731         }
3732
3733         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3734         //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]);
3735
3736         return skinframe;
3737 }
3738
3739 skinframe_t *R_SkinFrame_LoadMissing(void)
3740 {
3741         skinframe_t *skinframe;
3742
3743         if (cls.state == ca_dedicated)
3744                 return NULL;
3745
3746         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3747         skinframe->stain = NULL;
3748         skinframe->merged = NULL;
3749         skinframe->base = NULL;
3750         skinframe->pants = NULL;
3751         skinframe->shirt = NULL;
3752         skinframe->nmap = NULL;
3753         skinframe->gloss = NULL;
3754         skinframe->glow = NULL;
3755         skinframe->fog = NULL;
3756         skinframe->reflect = NULL;
3757         skinframe->hasalpha = false;
3758
3759         skinframe->avgcolor[0] = rand() / RAND_MAX;
3760         skinframe->avgcolor[1] = rand() / RAND_MAX;
3761         skinframe->avgcolor[2] = rand() / RAND_MAX;
3762         skinframe->avgcolor[3] = 1;
3763
3764         return skinframe;
3765 }
3766
3767 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3768 {
3769         int x, y;
3770         static unsigned char pix[16][16][4];
3771
3772         if (cls.state == ca_dedicated)
3773                 return NULL;
3774
3775         // this makes a light grey/dark grey checkerboard texture
3776         if (!pix[0][0][3])
3777         {
3778                 for (y = 0; y < 16; y++)
3779                 {
3780                         for (x = 0; x < 16; x++)
3781                         {
3782                                 if ((y < 8) ^ (x < 8))
3783                                 {
3784                                         pix[y][x][0] = 128;
3785                                         pix[y][x][1] = 128;
3786                                         pix[y][x][2] = 128;
3787                                         pix[y][x][3] = 255;
3788                                 }
3789                                 else
3790                                 {
3791                                         pix[y][x][0] = 64;
3792                                         pix[y][x][1] = 64;
3793                                         pix[y][x][2] = 64;
3794                                         pix[y][x][3] = 255;
3795                                 }
3796                         }
3797                 }
3798         }
3799
3800         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3801 }
3802
3803 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3804 {
3805         skinframe_t *skinframe;
3806         if (cls.state == ca_dedicated)
3807                 return NULL;
3808         // if already loaded just return it, otherwise make a new skinframe
3809         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3810         if (skinframe->base)
3811                 return skinframe;
3812         textureflags &= ~TEXF_FORCE_RELOAD;
3813         skinframe->stain = NULL;
3814         skinframe->merged = NULL;
3815         skinframe->base = NULL;
3816         skinframe->pants = NULL;
3817         skinframe->shirt = NULL;
3818         skinframe->nmap = NULL;
3819         skinframe->gloss = NULL;
3820         skinframe->glow = NULL;
3821         skinframe->fog = NULL;
3822         skinframe->reflect = NULL;
3823         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3824         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3825         if (!tex)
3826                 return NULL;
3827         if (developer_loading.integer)
3828                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3829         skinframe->base = skinframe->merged = tex;
3830         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3831         return skinframe;
3832 }
3833
3834 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3835 typedef struct suffixinfo_s
3836 {
3837         const char *suffix;
3838         qboolean flipx, flipy, flipdiagonal;
3839 }
3840 suffixinfo_t;
3841 static suffixinfo_t suffix[3][6] =
3842 {
3843         {
3844                 {"px",   false, false, false},
3845                 {"nx",   false, false, false},
3846                 {"py",   false, false, false},
3847                 {"ny",   false, false, false},
3848                 {"pz",   false, false, false},
3849                 {"nz",   false, false, false}
3850         },
3851         {
3852                 {"posx", false, false, false},
3853                 {"negx", false, false, false},
3854                 {"posy", false, false, false},
3855                 {"negy", false, false, false},
3856                 {"posz", false, false, false},
3857                 {"negz", false, false, false}
3858         },
3859         {
3860                 {"rt",    true, false,  true},
3861                 {"lf",   false,  true,  true},
3862                 {"ft",    true,  true, false},
3863                 {"bk",   false, false, false},
3864                 {"up",    true, false,  true},
3865                 {"dn",    true, false,  true}
3866         }
3867 };
3868
3869 static int componentorder[4] = {0, 1, 2, 3};
3870
3871 static rtexture_t *R_LoadCubemap(const char *basename)
3872 {
3873         int i, j, cubemapsize;
3874         unsigned char *cubemappixels, *image_buffer;
3875         rtexture_t *cubemaptexture;
3876         char name[256];
3877         // must start 0 so the first loadimagepixels has no requested width/height
3878         cubemapsize = 0;
3879         cubemappixels = NULL;
3880         cubemaptexture = NULL;
3881         // keep trying different suffix groups (posx, px, rt) until one loads
3882         for (j = 0;j < 3 && !cubemappixels;j++)
3883         {
3884                 // load the 6 images in the suffix group
3885                 for (i = 0;i < 6;i++)
3886                 {
3887                         // generate an image name based on the base and and suffix
3888                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3889                         // load it
3890                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3891                         {
3892                                 // an image loaded, make sure width and height are equal
3893                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3894                                 {
3895                                         // if this is the first image to load successfully, allocate the cubemap memory
3896                                         if (!cubemappixels && image_width >= 1)
3897                                         {
3898                                                 cubemapsize = image_width;
3899                                                 // note this clears to black, so unavailable sides are black
3900                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3901                                         }
3902                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3903                                         if (cubemappixels)
3904                                                 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);
3905                                 }
3906                                 else
3907                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3908                                 // free the image
3909                                 Mem_Free(image_buffer);
3910                         }
3911                 }
3912         }
3913         // if a cubemap loaded, upload it
3914         if (cubemappixels)
3915         {
3916                 if (developer_loading.integer)
3917                         Con_Printf("loading cubemap \"%s\"\n", basename);
3918
3919                 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);
3920                 Mem_Free(cubemappixels);
3921         }
3922         else
3923         {
3924                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3925                 if (developer_loading.integer)
3926                 {
3927                         Con_Printf("(tried tried images ");
3928                         for (j = 0;j < 3;j++)
3929                                 for (i = 0;i < 6;i++)
3930                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3931                         Con_Print(" and was unable to find any of them).\n");
3932                 }
3933         }
3934         return cubemaptexture;
3935 }
3936
3937 rtexture_t *R_GetCubemap(const char *basename)
3938 {
3939         int i;
3940         for (i = 0;i < r_texture_numcubemaps;i++)
3941                 if (r_texture_cubemaps[i] != NULL)
3942                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3943                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3944         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3945                 return r_texture_whitecube;
3946         r_texture_numcubemaps++;
3947         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3948         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3949         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3950         return r_texture_cubemaps[i]->texture;
3951 }
3952
3953 static void R_Main_FreeViewCache(void)
3954 {
3955         if (r_refdef.viewcache.entityvisible)
3956                 Mem_Free(r_refdef.viewcache.entityvisible);
3957         if (r_refdef.viewcache.world_pvsbits)
3958                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3959         if (r_refdef.viewcache.world_leafvisible)
3960                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3961         if (r_refdef.viewcache.world_surfacevisible)
3962                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3964 }
3965
3966 static void R_Main_ResizeViewCache(void)
3967 {
3968         int numentities = r_refdef.scene.numentities;
3969         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3970         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3971         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3972         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3973         if (r_refdef.viewcache.maxentities < numentities)
3974         {
3975                 r_refdef.viewcache.maxentities = numentities;
3976                 if (r_refdef.viewcache.entityvisible)
3977                         Mem_Free(r_refdef.viewcache.entityvisible);
3978                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3979         }
3980         if (r_refdef.viewcache.world_numclusters != numclusters)
3981         {
3982                 r_refdef.viewcache.world_numclusters = numclusters;
3983                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3984                 if (r_refdef.viewcache.world_pvsbits)
3985                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3986                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3987         }
3988         if (r_refdef.viewcache.world_numleafs != numleafs)
3989         {
3990                 r_refdef.viewcache.world_numleafs = numleafs;
3991                 if (r_refdef.viewcache.world_leafvisible)
3992                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3993                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3994         }
3995         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3996         {
3997                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3998                 if (r_refdef.viewcache.world_surfacevisible)
3999                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4000                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4001         }
4002 }
4003
4004 extern rtexture_t *loadingscreentexture;
4005 static void gl_main_start(void)
4006 {
4007         loadingscreentexture = NULL;
4008         r_texture_blanknormalmap = NULL;
4009         r_texture_white = NULL;
4010         r_texture_grey128 = NULL;
4011         r_texture_black = NULL;
4012         r_texture_whitecube = NULL;
4013         r_texture_normalizationcube = NULL;
4014         r_texture_fogattenuation = NULL;
4015         r_texture_fogheighttexture = NULL;
4016         r_texture_gammaramps = NULL;
4017         r_texture_numcubemaps = 0;
4018         r_uniformbufferalignment = 32;
4019
4020         r_loaddds = r_texture_dds_load.integer != 0;
4021         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4022
4023         switch(vid.renderpath)
4024         {
4025         case RENDERPATH_GL20:
4026         case RENDERPATH_D3D9:
4027         case RENDERPATH_D3D10:
4028         case RENDERPATH_D3D11:
4029         case RENDERPATH_SOFT:
4030         case RENDERPATH_GLES2:
4031                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032                 Cvar_SetValueQuick(&gl_combine, 1);
4033                 Cvar_SetValueQuick(&r_glsl, 1);
4034                 r_loadnormalmap = true;
4035                 r_loadgloss = true;
4036                 r_loadfog = false;
4037 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4038                 if (vid.support.arb_uniform_buffer_object)
4039                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4040 #endif
4041                         break;
4042         case RENDERPATH_GL13:
4043         case RENDERPATH_GLES1:
4044                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045                 Cvar_SetValueQuick(&gl_combine, 1);
4046                 Cvar_SetValueQuick(&r_glsl, 0);
4047                 r_loadnormalmap = false;
4048                 r_loadgloss = false;
4049                 r_loadfog = true;
4050                 break;
4051         case RENDERPATH_GL11:
4052                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053                 Cvar_SetValueQuick(&gl_combine, 0);
4054                 Cvar_SetValueQuick(&r_glsl, 0);
4055                 r_loadnormalmap = false;
4056                 r_loadgloss = false;
4057                 r_loadfog = true;
4058                 break;
4059         }
4060
4061         R_AnimCache_Free();
4062         R_FrameData_Reset();
4063         R_BufferData_Reset();
4064
4065         r_numqueries = 0;
4066         r_maxqueries = 0;
4067         memset(r_queries, 0, sizeof(r_queries));
4068
4069         r_qwskincache = NULL;
4070         r_qwskincache_size = 0;
4071
4072         // due to caching of texture_t references, the collision cache must be reset
4073         Collision_Cache_Reset(true);
4074
4075         // set up r_skinframe loading system for textures
4076         memset(&r_skinframe, 0, sizeof(r_skinframe));
4077         r_skinframe.loadsequence = 1;
4078         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4079
4080         r_main_texturepool = R_AllocTexturePool();
4081         R_BuildBlankTextures();
4082         R_BuildNoTexture();
4083         if (vid.support.arb_texture_cube_map)
4084         {
4085                 R_BuildWhiteCube();
4086                 R_BuildNormalizationCube();
4087         }
4088         r_texture_fogattenuation = NULL;
4089         r_texture_fogheighttexture = NULL;
4090         r_texture_gammaramps = NULL;
4091         //r_texture_fogintensity = NULL;
4092         memset(&r_fb, 0, sizeof(r_fb));
4093         r_glsl_permutation = NULL;
4094         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4096 #ifdef SUPPORTD3D
4097         r_hlsl_permutation = NULL;
4098         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4099         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4100 #endif
4101         memset(&r_svbsp, 0, sizeof (r_svbsp));
4102
4103         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4104         r_texture_numcubemaps = 0;
4105
4106         r_refdef.fogmasktable_density = 0;
4107
4108 #ifdef __ANDROID__
4109         // For Steelstorm Android
4110         // FIXME CACHE the program and reload
4111         // FIXME see possible combinations for SS:BR android
4112         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4113         R_SetupShader_SetPermutationGLSL(0, 12);
4114         R_SetupShader_SetPermutationGLSL(0, 13);
4115         R_SetupShader_SetPermutationGLSL(0, 8388621);
4116         R_SetupShader_SetPermutationGLSL(3, 0);
4117         R_SetupShader_SetPermutationGLSL(3, 2048);
4118         R_SetupShader_SetPermutationGLSL(5, 0);
4119         R_SetupShader_SetPermutationGLSL(5, 2);
4120         R_SetupShader_SetPermutationGLSL(5, 2048);
4121         R_SetupShader_SetPermutationGLSL(5, 8388608);
4122         R_SetupShader_SetPermutationGLSL(11, 1);
4123         R_SetupShader_SetPermutationGLSL(11, 2049);
4124         R_SetupShader_SetPermutationGLSL(11, 8193);
4125         R_SetupShader_SetPermutationGLSL(11, 10241);
4126         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4127 #endif
4128 }
4129
4130 static void gl_main_shutdown(void)
4131 {
4132         R_AnimCache_Free();
4133         R_FrameData_Reset();
4134         R_BufferData_Reset();
4135
4136         R_Main_FreeViewCache();
4137
4138         switch(vid.renderpath)
4139         {
4140         case RENDERPATH_GL11:
4141         case RENDERPATH_GL13:
4142         case RENDERPATH_GL20:
4143         case RENDERPATH_GLES1:
4144         case RENDERPATH_GLES2:
4145 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4146                 if (r_maxqueries)
4147                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4148 #endif
4149                 break;
4150         case RENDERPATH_D3D9:
4151                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4152                 break;
4153         case RENDERPATH_D3D10:
4154                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4155                 break;
4156         case RENDERPATH_D3D11:
4157                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4158                 break;
4159         case RENDERPATH_SOFT:
4160                 break;
4161         }
4162
4163         r_numqueries = 0;
4164         r_maxqueries = 0;
4165         memset(r_queries, 0, sizeof(r_queries));
4166
4167         r_qwskincache = NULL;
4168         r_qwskincache_size = 0;
4169
4170         // clear out the r_skinframe state
4171         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4172         memset(&r_skinframe, 0, sizeof(r_skinframe));
4173
4174         if (r_svbsp.nodes)
4175                 Mem_Free(r_svbsp.nodes);
4176         memset(&r_svbsp, 0, sizeof (r_svbsp));
4177         R_FreeTexturePool(&r_main_texturepool);
4178         loadingscreentexture = NULL;
4179         r_texture_blanknormalmap = NULL;
4180         r_texture_white = NULL;
4181         r_texture_grey128 = NULL;
4182         r_texture_black = NULL;
4183         r_texture_whitecube = NULL;
4184         r_texture_normalizationcube = NULL;
4185         r_texture_fogattenuation = NULL;
4186         r_texture_fogheighttexture = NULL;
4187         r_texture_gammaramps = NULL;
4188         r_texture_numcubemaps = 0;
4189         //r_texture_fogintensity = NULL;
4190         memset(&r_fb, 0, sizeof(r_fb));
4191         R_GLSL_Restart_f();
4192
4193         r_glsl_permutation = NULL;
4194         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4195         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4196 #ifdef SUPPORTD3D
4197         r_hlsl_permutation = NULL;
4198         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4199         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4200 #endif
4201 }
4202
4203 static void gl_main_newmap(void)
4204 {
4205         // FIXME: move this code to client
4206         char *entities, entname[MAX_QPATH];
4207         if (r_qwskincache)
4208                 Mem_Free(r_qwskincache);
4209         r_qwskincache = NULL;
4210         r_qwskincache_size = 0;
4211         if (cl.worldmodel)
4212         {
4213                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4214                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4215                 {
4216                         CL_ParseEntityLump(entities);
4217                         Mem_Free(entities);
4218                         return;
4219                 }
4220                 if (cl.worldmodel->brush.entities)
4221                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4222         }
4223         R_Main_FreeViewCache();
4224
4225         R_FrameData_Reset();
4226         R_BufferData_Reset();
4227 }
4228
4229 void GL_Main_Init(void)
4230 {
4231         int i;
4232         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4233         R_InitShaderModeInfo();
4234
4235         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4236         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4237         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4238         if (gamemode == GAME_NEHAHRA)
4239         {
4240                 Cvar_RegisterVariable (&gl_fogenable);
4241                 Cvar_RegisterVariable (&gl_fogdensity);
4242                 Cvar_RegisterVariable (&gl_fogred);
4243                 Cvar_RegisterVariable (&gl_foggreen);
4244                 Cvar_RegisterVariable (&gl_fogblue);
4245                 Cvar_RegisterVariable (&gl_fogstart);
4246                 Cvar_RegisterVariable (&gl_fogend);
4247                 Cvar_RegisterVariable (&gl_skyclip);
4248         }
4249         Cvar_RegisterVariable(&r_motionblur);
4250         Cvar_RegisterVariable(&r_damageblur);
4251         Cvar_RegisterVariable(&r_motionblur_averaging);
4252         Cvar_RegisterVariable(&r_motionblur_randomize);
4253         Cvar_RegisterVariable(&r_motionblur_minblur);
4254         Cvar_RegisterVariable(&r_motionblur_maxblur);
4255         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4256         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4257         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4258         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4259         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4260         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4261         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4262         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4263         Cvar_RegisterVariable(&r_equalize_entities_by);
4264         Cvar_RegisterVariable(&r_equalize_entities_to);
4265         Cvar_RegisterVariable(&r_depthfirst);
4266         Cvar_RegisterVariable(&r_useinfinitefarclip);
4267         Cvar_RegisterVariable(&r_farclip_base);
4268         Cvar_RegisterVariable(&r_farclip_world);
4269         Cvar_RegisterVariable(&r_nearclip);
4270         Cvar_RegisterVariable(&r_deformvertexes);
4271         Cvar_RegisterVariable(&r_transparent);
4272         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4273         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4274         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4275         Cvar_RegisterVariable(&r_showoverdraw);
4276         Cvar_RegisterVariable(&r_showbboxes);
4277         Cvar_RegisterVariable(&r_showbboxes_client);
4278         Cvar_RegisterVariable(&r_showsurfaces);
4279         Cvar_RegisterVariable(&r_showtris);
4280         Cvar_RegisterVariable(&r_shownormals);
4281         Cvar_RegisterVariable(&r_showlighting);
4282         Cvar_RegisterVariable(&r_showshadowvolumes);
4283         Cvar_RegisterVariable(&r_showcollisionbrushes);
4284         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4285         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4286         Cvar_RegisterVariable(&r_showdisabledepthtest);
4287         Cvar_RegisterVariable(&r_drawportals);
4288         Cvar_RegisterVariable(&r_drawentities);
4289         Cvar_RegisterVariable(&r_draw2d);
4290         Cvar_RegisterVariable(&r_drawworld);
4291         Cvar_RegisterVariable(&r_cullentities_trace);
4292         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4293         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4294         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4295         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4296         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4297         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4298         Cvar_RegisterVariable(&r_sortentities);
4299         Cvar_RegisterVariable(&r_drawviewmodel);
4300         Cvar_RegisterVariable(&r_drawexteriormodel);
4301         Cvar_RegisterVariable(&r_speeds);
4302         Cvar_RegisterVariable(&r_fullbrights);
4303         Cvar_RegisterVariable(&r_wateralpha);
4304         Cvar_RegisterVariable(&r_dynamic);
4305         Cvar_RegisterVariable(&r_fakelight);
4306         Cvar_RegisterVariable(&r_fakelight_intensity);
4307         Cvar_RegisterVariable(&r_fullbright_directed);
4308         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4309         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4310         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4311         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4312         Cvar_RegisterVariable(&r_fullbright);
4313         Cvar_RegisterVariable(&r_shadows);
4314         Cvar_RegisterVariable(&r_shadows_darken);
4315         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317         Cvar_RegisterVariable(&r_shadows_throwdistance);
4318         Cvar_RegisterVariable(&r_shadows_throwdirection);
4319         Cvar_RegisterVariable(&r_shadows_focus);
4320         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327         Cvar_RegisterVariable(&r_fog_exp2);
4328         Cvar_RegisterVariable(&r_fog_clear);
4329         Cvar_RegisterVariable(&r_drawfog);
4330         Cvar_RegisterVariable(&r_transparentdepthmasking);
4331         Cvar_RegisterVariable(&r_transparent_sortmindist);
4332         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334         Cvar_RegisterVariable(&r_texture_dds_load);
4335         Cvar_RegisterVariable(&r_texture_dds_save);
4336         Cvar_RegisterVariable(&r_textureunits);
4337         Cvar_RegisterVariable(&gl_combine);
4338         Cvar_RegisterVariable(&r_usedepthtextures);
4339         Cvar_RegisterVariable(&r_viewfbo);
4340         Cvar_RegisterVariable(&r_viewscale);
4341         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347         Cvar_RegisterVariable(&r_glsl);
4348         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357         Cvar_RegisterVariable(&r_glsl_postprocess);
4358         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366         Cvar_RegisterVariable(&r_celshading);
4367         Cvar_RegisterVariable(&r_celoutlines);
4368
4369         Cvar_RegisterVariable(&r_water);
4370         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4371         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4372         Cvar_RegisterVariable(&r_water_clippingplanebias);
4373         Cvar_RegisterVariable(&r_water_refractdistort);
4374         Cvar_RegisterVariable(&r_water_reflectdistort);
4375         Cvar_RegisterVariable(&r_water_scissormode);
4376         Cvar_RegisterVariable(&r_water_lowquality);
4377         Cvar_RegisterVariable(&r_water_hideplayer);
4378         Cvar_RegisterVariable(&r_water_fbo);
4379
4380         Cvar_RegisterVariable(&r_lerpsprites);
4381         Cvar_RegisterVariable(&r_lerpmodels);
4382         Cvar_RegisterVariable(&r_lerplightstyles);
4383         Cvar_RegisterVariable(&r_waterscroll);
4384         Cvar_RegisterVariable(&r_bloom);
4385         Cvar_RegisterVariable(&r_bloom_colorscale);
4386         Cvar_RegisterVariable(&r_bloom_brighten);
4387         Cvar_RegisterVariable(&r_bloom_blur);
4388         Cvar_RegisterVariable(&r_bloom_resolution);
4389         Cvar_RegisterVariable(&r_bloom_colorexponent);
4390         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4391         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4392         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4393         Cvar_RegisterVariable(&r_hdr_glowintensity);
4394         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4395         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4396         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4397         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4401         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4402         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4403         Cvar_RegisterVariable(&developer_texturelogging);
4404         Cvar_RegisterVariable(&gl_lightmaps);
4405         Cvar_RegisterVariable(&r_test);
4406         Cvar_RegisterVariable(&r_batch_multidraw);
4407         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4408         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4409         Cvar_RegisterVariable(&r_glsl_skeletal);
4410         Cvar_RegisterVariable(&r_glsl_saturation);
4411         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4412         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4413         Cvar_RegisterVariable(&r_framedatasize);
4414         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4415                 Cvar_RegisterVariable(&r_buffermegs[i]);
4416         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4417         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4418                 Cvar_SetValue("r_fullbrights", 0);
4419 #ifdef DP_MOBILETOUCH
4420         // GLES devices have terrible depth precision in general, so...
4421         Cvar_SetValueQuick(&r_nearclip, 4);
4422         Cvar_SetValueQuick(&r_farclip_base, 4096);
4423         Cvar_SetValueQuick(&r_farclip_world, 0);
4424         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 #endif
4426         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4427 }
4428
4429 void Render_Init(void)
4430 {
4431         gl_backend_init();
4432         R_Textures_Init();
4433         GL_Main_Init();
4434         Font_Init();
4435         GL_Draw_Init();
4436         R_Shadow_Init();
4437         R_Sky_Init();
4438         GL_Surf_Init();
4439         Sbar_Init();
4440         R_Particles_Init();
4441         R_Explosion_Init();
4442         R_LightningBeams_Init();
4443         Mod_RenderInit();
4444 }
4445
4446 /*
4447 ===============
4448 GL_Init
4449 ===============
4450 */
4451 #ifndef USE_GLES2
4452 extern char *ENGINE_EXTENSIONS;
4453 void GL_Init (void)
4454 {
4455         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4456         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4457         gl_version = (const char *)qglGetString(GL_VERSION);
4458         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4459
4460         if (!gl_extensions)
4461                 gl_extensions = "";
4462         if (!gl_platformextensions)
4463                 gl_platformextensions = "";
4464
4465         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4466         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4467         Con_Printf("GL_VERSION: %s\n", gl_version);
4468         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4469         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470
4471         VID_CheckExtensions();
4472
4473         // LordHavoc: report supported extensions
4474 #ifdef CONFIG_MENU
4475         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 #else
4477         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4478 #endif
4479
4480         // clear to black (loading plaque will be seen over this)
4481         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4482 }
4483 #endif
4484
4485 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4486 {
4487         int i;
4488         mplane_t *p;
4489         if (r_trippy.integer)
4490                 return false;
4491         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492         {
4493                 p = r_refdef.view.frustum + i;
4494                 switch(p->signbits)
4495                 {
4496                 default:
4497                 case 0:
4498                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499                                 return true;
4500                         break;
4501                 case 1:
4502                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 2:
4506                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 3:
4510                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 4:
4514                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 5:
4518                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 6:
4522                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 7:
4526                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 }
4530         }
4531         return false;
4532 }
4533
4534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4535 {
4536         int i;
4537         const mplane_t *p;
4538         if (r_trippy.integer)
4539                 return false;
4540         for (i = 0;i < numplanes;i++)
4541         {
4542                 p = planes + i;
4543                 switch(p->signbits)
4544                 {
4545                 default:
4546                 case 0:
4547                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4548                                 return true;
4549                         break;
4550                 case 1:
4551                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4552                                 return true;
4553                         break;
4554                 case 2:
4555                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4556                                 return true;
4557                         break;
4558                 case 3:
4559                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4560                                 return true;
4561                         break;
4562                 case 4:
4563                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 5:
4567                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 6:
4571                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 7:
4575                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 }
4579         }
4580         return false;
4581 }
4582
4583 //==================================================================================
4584
4585 // LordHavoc: this stores temporary data used within the same frame
4586
4587 typedef struct r_framedata_mem_s
4588 {
4589         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4590         size_t size; // how much usable space
4591         size_t current; // how much space in use
4592         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4593         size_t wantedsize; // how much space was allocated
4594         unsigned char *data; // start of real data (16byte aligned)
4595 }
4596 r_framedata_mem_t;
4597
4598 static r_framedata_mem_t *r_framedata_mem;
4599
4600 void R_FrameData_Reset(void)
4601 {
4602         while (r_framedata_mem)
4603         {
4604                 r_framedata_mem_t *next = r_framedata_mem->purge;
4605                 Mem_Free(r_framedata_mem);
4606                 r_framedata_mem = next;
4607         }
4608 }
4609
4610 static void R_FrameData_Resize(qboolean mustgrow)
4611 {
4612         size_t wantedsize;
4613         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4614         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4615         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4616         {
4617                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4618                 newmem->wantedsize = wantedsize;
4619                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4620                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4621                 newmem->current = 0;
4622                 newmem->mark = 0;
4623                 newmem->purge = r_framedata_mem;
4624                 r_framedata_mem = newmem;
4625         }
4626 }
4627
4628 void R_FrameData_NewFrame(void)
4629 {
4630         R_FrameData_Resize(false);
4631         if (!r_framedata_mem)
4632                 return;
4633         // if we ran out of space on the last frame, free the old memory now
4634         while (r_framedata_mem->purge)
4635         {
4636                 // repeatedly remove the second item in the list, leaving only head
4637                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4638                 Mem_Free(r_framedata_mem->purge);
4639                 r_framedata_mem->purge = next;
4640         }
4641         // reset the current mem pointer
4642         r_framedata_mem->current = 0;
4643         r_framedata_mem->mark = 0;
4644 }
4645
4646 void *R_FrameData_Alloc(size_t size)
4647 {
4648         void *data;
4649         float newvalue;
4650
4651         // align to 16 byte boundary - the data pointer is already aligned, so we
4652         // only need to ensure the size of every allocation is also aligned
4653         size = (size + 15) & ~15;
4654
4655         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4656         {
4657                 // emergency - we ran out of space, allocate more memory
4658                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4659                 newvalue = r_framedatasize.value * 2.0f;
4660                 // 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
4661                 if (sizeof(size_t) >= 8)
4662                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4663                 else
4664                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4665                 // this might not be a growing it, but we'll allocate another buffer every time
4666                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4667                 R_FrameData_Resize(true);
4668         }
4669
4670         data = r_framedata_mem->data + r_framedata_mem->current;
4671         r_framedata_mem->current += size;
4672
4673         // count the usage for stats
4674         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4675         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4676
4677         return (void *)data;
4678 }
4679
4680 void *R_FrameData_Store(size_t size, void *data)
4681 {
4682         void *d = R_FrameData_Alloc(size);
4683         if (d && data)
4684                 memcpy(d, data, size);
4685         return d;
4686 }
4687
4688 void R_FrameData_SetMark(void)
4689 {
4690         if (!r_framedata_mem)
4691                 return;
4692         r_framedata_mem->mark = r_framedata_mem->current;
4693 }
4694
4695 void R_FrameData_ReturnToMark(void)
4696 {
4697         if (!r_framedata_mem)
4698                 return;
4699         r_framedata_mem->current = r_framedata_mem->mark;
4700 }
4701
4702 //==================================================================================
4703
4704 // avoid reusing the same buffer objects on consecutive frames
4705 #define R_BUFFERDATA_CYCLE 3
4706
4707 typedef struct r_bufferdata_buffer_s
4708 {
4709         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4710         size_t size; // how much usable space
4711         size_t current; // how much space in use
4712         r_meshbuffer_t *buffer; // the buffer itself
4713 }
4714 r_bufferdata_buffer_t;
4715
4716 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4717 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4718
4719 /// frees all dynamic buffers
4720 void R_BufferData_Reset(void)
4721 {
4722         int cycle, type;
4723         r_bufferdata_buffer_t **p, *mem;
4724         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4725         {
4726                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4727                 {
4728                         // free all buffers
4729                         p = &r_bufferdata_buffer[cycle][type];
4730                         while (*p)
4731                         {
4732                                 mem = *p;
4733                                 *p = (*p)->purge;
4734                                 if (mem->buffer)
4735                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4736                                 Mem_Free(mem);
4737                         }
4738                 }
4739         }
4740 }
4741
4742 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4743 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4744 {
4745         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4746         size_t size;
4747         float newvalue = r_buffermegs[type].value;
4748
4749         // increase the cvar if we have to (but only if we already have a mem)
4750         if (mustgrow && mem)
4751                 newvalue *= 2.0f;
4752         newvalue = bound(0.25f, newvalue, 256.0f);
4753         while (newvalue * 1024*1024 < minsize)
4754                 newvalue *= 2.0f;
4755
4756         // clamp the cvar to valid range
4757         newvalue = bound(0.25f, newvalue, 256.0f);
4758         if (r_buffermegs[type].value != newvalue)
4759                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4760
4761         // calculate size in bytes
4762         size = (size_t)(newvalue * 1024*1024);
4763         size = bound(131072, size, 256*1024*1024);
4764
4765         // allocate a new buffer if the size is different (purge old one later)
4766         // or if we were told we must grow the buffer
4767         if (!mem || mem->size != size || mustgrow)
4768         {
4769                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4770                 mem->size = size;
4771                 mem->current = 0;
4772                 if (type == R_BUFFERDATA_VERTEX)
4773                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4774                 else if (type == R_BUFFERDATA_INDEX16)
4775                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4776                 else if (type == R_BUFFERDATA_INDEX32)
4777                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4778                 else if (type == R_BUFFERDATA_UNIFORM)
4779                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4780                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4782         }
4783 }
4784
4785 void R_BufferData_NewFrame(void)
4786 {
4787         int type;
4788         r_bufferdata_buffer_t **p, *mem;
4789         // cycle to the next frame's buffers
4790         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4791         // if we ran out of space on the last time we used these buffers, free the old memory now
4792         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4793         {
4794                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4795                 {
4796                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4797                         // free all but the head buffer, this is how we recycle obsolete
4798                         // buffers after they are no longer in use
4799                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4800                         while (*p)
4801                         {
4802                                 mem = *p;
4803                                 *p = (*p)->purge;
4804                                 if (mem->buffer)
4805                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4806                                 Mem_Free(mem);
4807                         }
4808                         // reset the current offset
4809                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810                 }
4811         }
4812 }
4813
4814 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4815 {
4816         r_bufferdata_buffer_t *mem;
4817         int offset = 0;
4818         int padsize;
4819
4820         *returnbufferoffset = 0;
4821
4822         // align size to a byte boundary appropriate for the buffer type, this
4823         // makes all allocations have aligned start offsets
4824         if (type == R_BUFFERDATA_UNIFORM)
4825                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4826         else
4827                 padsize = (datasize + 15) & ~15;
4828
4829         // if we ran out of space in this buffer we must allocate a new one
4830         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)
4831                 R_BufferData_Resize(type, true, padsize);
4832
4833         // if the resize did not give us enough memory, fail
4834         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)
4835                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4836
4837         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4838         offset = (int)mem->current;
4839         mem->current += padsize;
4840
4841         // upload the data to the buffer at the chosen offset
4842         if (offset == 0)
4843                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4844         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4845
4846         // count the usage for stats
4847         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4848         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4849
4850         // return the buffer offset
4851         *returnbufferoffset = offset;
4852
4853         return mem->buffer;
4854 }
4855
4856 //==================================================================================
4857
4858 // LordHavoc: animcache originally written by Echon, rewritten since then
4859
4860 /**
4861  * Animation cache prevents re-generating mesh data for an animated model
4862  * multiple times in one frame for lighting, shadowing, reflections, etc.
4863  */
4864
4865 void R_AnimCache_Free(void)
4866 {
4867 }
4868
4869 void R_AnimCache_ClearCache(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 ent = r_refdef.scene.entities[i];
4877                 ent->animcache_vertex3f = NULL;
4878                 ent->animcache_vertex3f_vertexbuffer = NULL;
4879                 ent->animcache_vertex3f_bufferoffset = 0;
4880                 ent->animcache_normal3f = NULL;
4881                 ent->animcache_normal3f_vertexbuffer = NULL;
4882                 ent->animcache_normal3f_bufferoffset = 0;
4883                 ent->animcache_svector3f = NULL;
4884                 ent->animcache_svector3f_vertexbuffer = NULL;
4885                 ent->animcache_svector3f_bufferoffset = 0;
4886                 ent->animcache_tvector3f = NULL;
4887                 ent->animcache_tvector3f_vertexbuffer = NULL;
4888                 ent->animcache_tvector3f_bufferoffset = 0;
4889                 ent->animcache_vertexmesh = NULL;
4890                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4891                 ent->animcache_vertexmesh_bufferoffset = 0;
4892                 ent->animcache_skeletaltransform3x4 = NULL;
4893                 ent->animcache_skeletaltransform3x4buffer = NULL;
4894                 ent->animcache_skeletaltransform3x4offset = 0;
4895                 ent->animcache_skeletaltransform3x4size = 0;
4896         }
4897 }
4898
4899 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4900 {
4901         int i;
4902
4903         // check if we need the meshbuffers
4904         if (!vid.useinterleavedarrays)
4905                 return;
4906
4907         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4908                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4909         // TODO: upload vertexbuffer?
4910         if (ent->animcache_vertexmesh)
4911         {
4912                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4913                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4914                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4915                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4916                 for (i = 0;i < numvertices;i++)
4917                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4918                 if (ent->animcache_svector3f)
4919                         for (i = 0;i < numvertices;i++)
4920                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4921                 if (ent->animcache_tvector3f)
4922                         for (i = 0;i < numvertices;i++)
4923                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4924                 if (ent->animcache_normal3f)
4925                         for (i = 0;i < numvertices;i++)
4926                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4927         }
4928 }
4929
4930 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4931 {
4932         dp_model_t *model = ent->model;
4933         int numvertices;
4934
4935         // see if this ent is worth caching
4936         if (!model || !model->Draw || !model->AnimateVertices)
4937                 return false;
4938         // nothing to cache if it contains no animations and has no skeleton
4939         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4940                 return false;
4941         // see if it is already cached for gpuskeletal
4942         if (ent->animcache_skeletaltransform3x4)
4943                 return false;
4944         // see if it is already cached as a mesh
4945         if (ent->animcache_vertex3f)
4946         {
4947                 // check if we need to add normals or tangents
4948                 if (ent->animcache_normal3f)
4949                         wantnormals = false;
4950                 if (ent->animcache_svector3f)
4951                         wanttangents = false;
4952                 if (!wantnormals && !wanttangents)
4953                         return false;
4954         }
4955
4956         // check which kind of cache we need to generate
4957         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4958         {
4959                 // cache the skeleton so the vertex shader can use it
4960                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4961                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4962                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4963                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4964                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4965                 // note: this can fail if the buffer is at the grow limit
4966                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4967                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4968         }
4969         else if (ent->animcache_vertex3f)
4970         {
4971                 // mesh was already cached but we may need to add normals/tangents
4972                 // (this only happens with multiple views, reflections, cameras, etc)
4973                 if (wantnormals || wanttangents)
4974                 {
4975                         numvertices = model->surfmesh.num_vertices;
4976                         if (wantnormals)
4977                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         if (wanttangents)
4979                         {
4980                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982                         }
4983                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4984                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4986                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4987                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988                 }
4989         }
4990         else
4991         {
4992                 // generate mesh cache
4993                 numvertices = model->surfmesh.num_vertices;
4994                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995                 if (wantnormals)
4996                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997                 if (wanttangents)
4998                 {
4999                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001                 }
5002                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5003                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5004                 if (wantnormals || wanttangents)
5005                 {
5006                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5009                 }
5010                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5011                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5012                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013         }
5014         return true;
5015 }
5016
5017 void R_AnimCache_CacheVisibleEntities(void)
5018 {
5019         int i;
5020         qboolean wantnormals = true;
5021         qboolean wanttangents = !r_showsurfaces.integer;
5022
5023         switch(vid.renderpath)
5024         {
5025         case RENDERPATH_GL20:
5026         case RENDERPATH_D3D9:
5027         case RENDERPATH_D3D10:
5028         case RENDERPATH_D3D11:
5029         case RENDERPATH_GLES2:
5030                 break;
5031         case RENDERPATH_GL11:
5032         case RENDERPATH_GL13:
5033         case RENDERPATH_GLES1:
5034                 wanttangents = false;
5035                 break;
5036         case RENDERPATH_SOFT:
5037                 break;
5038         }
5039
5040         if (r_shownormals.integer)
5041                 wanttangents = wantnormals = true;
5042
5043         // TODO: thread this
5044         // NOTE: R_PrepareRTLights() also caches entities
5045
5046         for (i = 0;i < r_refdef.scene.numentities;i++)
5047                 if (r_refdef.viewcache.entityvisible[i])
5048                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5049 }
5050
5051 //==================================================================================
5052
5053 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5054 {
5055         int i;
5056         vec3_t eyemins, eyemaxs;
5057         vec3_t boxmins, boxmaxs;
5058         vec3_t start;
5059         vec3_t end;
5060         dp_model_t *model = r_refdef.scene.worldmodel;
5061         static vec3_t positions[] = {
5062                 { 0.5f, 0.5f, 0.5f },
5063                 { 0.0f, 0.0f, 0.0f },
5064                 { 0.0f, 0.0f, 1.0f },
5065                 { 0.0f, 1.0f, 0.0f },
5066                 { 0.0f, 1.0f, 1.0f },
5067                 { 1.0f, 0.0f, 0.0f },
5068                 { 1.0f, 0.0f, 1.0f },
5069                 { 1.0f, 1.0f, 0.0f },
5070                 { 1.0f, 1.0f, 1.0f },
5071         };
5072
5073         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5074         if (numsamples < 0)
5075                 return true;
5076
5077         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5078         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5079                 return true;
5080
5081         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5082                 return true;
5083
5084         // expand the eye box a little
5085         eyemins[0] = eye[0] - eyejitter;
5086         eyemaxs[0] = eye[0] + eyejitter;
5087         eyemins[1] = eye[1] - eyejitter;
5088         eyemaxs[1] = eye[1] + eyejitter;
5089         eyemins[2] = eye[2] - eyejitter;
5090         eyemaxs[2] = eye[2] + eyejitter;
5091         // expand the box a little
5092         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5093         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5094         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5095         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5096         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5097         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5098
5099         // return true if eye overlaps enlarged box
5100         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5101                 return true;
5102
5103         // try specific positions in the box first - note that these can be cached
5104         if (r_cullentities_trace_entityocclusion.integer)
5105         {
5106                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5107                 {
5108                         VectorCopy(eye, start);
5109                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5110                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5111                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5112                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5113                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5114                         // not picky - if the trace ended anywhere in the box we're good
5115                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5116                                 return true;
5117                 }
5118         }
5119         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5120                 return true;
5121
5122         // try various random positions
5123         for (i = 0; i < numsamples; i++)
5124         {
5125                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5126                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5127                 if (r_cullentities_trace_entityocclusion.integer)
5128                 {
5129                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5130                         // not picky - if the trace ended anywhere in the box we're good
5131                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5132                                 return true;
5133                 }
5134                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5135                         return true;
5136         }
5137
5138         return false;
5139 }
5140
5141
5142 static void R_View_UpdateEntityVisible (void)
5143 {
5144         int i;
5145         int renderimask;
5146         int samples;
5147         entity_render_t *ent;
5148
5149         if (r_refdef.envmap || r_fb.water.hideplayer)
5150                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5151         else if (chase_active.integer || r_fb.water.renderingscene)
5152                 renderimask = RENDER_VIEWMODEL;
5153         else
5154                 renderimask = RENDER_EXTERIORMODEL;
5155         if (!r_drawviewmodel.integer)
5156                 renderimask |= RENDER_VIEWMODEL;
5157         if (!r_drawexteriormodel.integer)
5158                 renderimask |= RENDER_EXTERIORMODEL;
5159         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5160         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5161         {
5162                 // worldmodel can check visibility
5163                 for (i = 0;i < r_refdef.scene.numentities;i++)
5164                 {
5165                         ent = r_refdef.scene.entities[i];
5166                         if (!(ent->flags & renderimask))
5167                         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)))
5168                         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))
5169                                 r_refdef.viewcache.entityvisible[i] = true;
5170                 }
5171         }
5172         else
5173         {
5174                 // no worldmodel or it can't check visibility
5175                 for (i = 0;i < r_refdef.scene.numentities;i++)
5176                 {
5177                         ent = r_refdef.scene.entities[i];
5178                         if (!(ent->flags & renderimask))
5179                         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)))
5180                                 r_refdef.viewcache.entityvisible[i] = true;
5181                 }
5182         }
5183         if (r_cullentities_trace.integer)
5184         {
5185                 for (i = 0;i < r_refdef.scene.numentities;i++)
5186                 {
5187                         if (!r_refdef.viewcache.entityvisible[i])
5188                                 continue;
5189                         ent = r_refdef.scene.entities[i];
5190                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5191                         {
5192                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5193                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5194                                         ent->last_trace_visibility = realtime;
5195                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5196                                         r_refdef.viewcache.entityvisible[i] = 0;
5197                         }
5198                 }
5199         }
5200 }
5201
5202 /// only used if skyrendermasked, and normally returns false
5203 static int R_DrawBrushModelsSky (void)
5204 {
5205         int i, sky;
5206         entity_render_t *ent;
5207
5208         sky = false;
5209         for (i = 0;i < r_refdef.scene.numentities;i++)
5210         {
5211                 if (!r_refdef.viewcache.entityvisible[i])
5212                         continue;
5213                 ent = r_refdef.scene.entities[i];
5214                 if (!ent->model || !ent->model->DrawSky)
5215                         continue;
5216                 ent->model->DrawSky(ent);
5217                 sky = true;
5218         }
5219         return sky;
5220 }
5221
5222 static void R_DrawNoModel(entity_render_t *ent);
5223 static void R_DrawModels(void)
5224 {
5225         int i;
5226         entity_render_t *ent;
5227
5228         for (i = 0;i < r_refdef.scene.numentities;i++)
5229         {
5230                 if (!r_refdef.viewcache.entityvisible[i])
5231                         continue;
5232                 ent = r_refdef.scene.entities[i];
5233                 r_refdef.stats[r_stat_entities]++;
5234                 /*
5235                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5236                 {
5237                         vec3_t f, l, u, o;
5238                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5239                         Con_Printf("R_DrawModels\n");
5240                         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]);
5241                         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);
5242                         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);
5243                 }
5244                 */
5245                 if (ent->model && ent->model->Draw != NULL)
5246                         ent->model->Draw(ent);
5247                 else
5248                         R_DrawNoModel(ent);
5249         }
5250 }
5251
5252 static void R_DrawModelsDepth(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->DrawDepth != NULL)
5263                         ent->model->DrawDepth(ent);
5264         }
5265 }
5266
5267 static void R_DrawModelsDebug(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->DrawDebug != NULL)
5278                         ent->model->DrawDebug(ent);
5279         }
5280 }
5281
5282 static void R_DrawModelsAddWaterPlanes(void)
5283 {
5284         int i;
5285         entity_render_t *ent;
5286
5287         for (i = 0;i < r_refdef.scene.numentities;i++)
5288         {
5289                 if (!r_refdef.viewcache.entityvisible[i])
5290                         continue;
5291                 ent = r_refdef.scene.entities[i];
5292                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5293                         ent->model->DrawAddWaterPlanes(ent);
5294         }
5295 }
5296
5297 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}};
5298
5299 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5300 {
5301         if (r_hdr_irisadaptation.integer)
5302         {
5303                 vec3_t p;
5304                 vec3_t ambient;
5305                 vec3_t diffuse;
5306                 vec3_t diffusenormal;
5307                 vec3_t forward;
5308                 vec_t brightness = 0.0f;
5309                 vec_t goal;
5310                 vec_t current;
5311                 vec_t d;
5312                 int c;
5313                 VectorCopy(r_refdef.view.forward, forward);
5314                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5315                 {
5316                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5317                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5318                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5319                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5320                         d = DotProduct(forward, diffusenormal);
5321                         brightness += VectorLength(ambient);
5322                         if (d > 0)
5323                                 brightness += d * VectorLength(diffuse);
5324                 }
5325                 brightness *= 1.0f / c;
5326                 brightness += 0.00001f; // make sure it's never zero
5327                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5328                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5329                 current = r_hdr_irisadaptation_value.value;
5330                 if (current < goal)
5331                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5332                 else if (current > goal)
5333                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5334                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5335                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5336         }
5337         else if (r_hdr_irisadaptation_value.value != 1.0f)
5338                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5339 }
5340
5341 static void R_View_SetFrustum(const int *scissor)
5342 {
5343         int i;
5344         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5345         vec3_t forward, left, up, origin, v;
5346
5347         if(scissor)
5348         {
5349                 // flipped x coordinates (because x points left here)
5350                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5351                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5352
5353                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5354                 switch(vid.renderpath)
5355                 {
5356                         case RENDERPATH_D3D9:
5357                         case RENDERPATH_D3D10:
5358                         case RENDERPATH_D3D11:
5359                                 // non-flipped y coordinates
5360                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5362                                 break;
5363                         case RENDERPATH_SOFT:
5364                         case RENDERPATH_GL11:
5365                         case RENDERPATH_GL13:
5366                         case RENDERPATH_GL20:
5367                         case RENDERPATH_GLES1:
5368                         case RENDERPATH_GLES2:
5369                                 // non-flipped y coordinates
5370                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5371                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5372                                 break;
5373                 }
5374         }
5375
5376         // we can't trust r_refdef.view.forward and friends in reflected scenes
5377         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5378
5379 #if 0
5380         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5381         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5382         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5383         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5384         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5385         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5386         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5387         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5388         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5389         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5390         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5391         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5392 #endif
5393
5394 #if 0
5395         zNear = r_refdef.nearclip;
5396         nudge = 1.0 - 1.0 / (1<<23);
5397         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5398         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5399         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5400         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5401         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5402         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5403         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5404         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5405 #endif
5406
5407
5408
5409 #if 0
5410         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5411         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5412         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5413         r_refdef.view.frustum[0].dist = m[15] - m[12];
5414
5415         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5416         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5417         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5418         r_refdef.view.frustum[1].dist = m[15] + m[12];
5419
5420         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5421         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5422         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5423         r_refdef.view.frustum[2].dist = m[15] - m[13];
5424
5425         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5426         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5427         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5428         r_refdef.view.frustum[3].dist = m[15] + m[13];
5429
5430         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5431         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5432         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5433         r_refdef.view.frustum[4].dist = m[15] - m[14];
5434
5435         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5436         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5437         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5438         r_refdef.view.frustum[5].dist = m[15] + m[14];
5439 #endif
5440
5441         if (r_refdef.view.useperspective)
5442         {
5443                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5444                 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]);
5445                 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]);
5446                 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]);
5447                 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]);
5448
5449                 // then the normals from the corners relative to origin
5450                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5451                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5452                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5453                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5454
5455                 // in a NORMAL view, forward cross left == up
5456                 // in a REFLECTED view, forward cross left == down
5457                 // so our cross products above need to be adjusted for a left handed coordinate system
5458                 CrossProduct(forward, left, v);
5459                 if(DotProduct(v, up) < 0)
5460                 {
5461                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5462                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5463                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5464                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5465                 }
5466
5467                 // Leaving those out was a mistake, those were in the old code, and they
5468                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5469                 // I couldn't reproduce it after adding those normalizations. --blub
5470                 VectorNormalize(r_refdef.view.frustum[0].normal);
5471                 VectorNormalize(r_refdef.view.frustum[1].normal);
5472                 VectorNormalize(r_refdef.view.frustum[2].normal);
5473                 VectorNormalize(r_refdef.view.frustum[3].normal);
5474
5475                 // make the corners absolute
5476                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5477                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5478                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5479                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5480
5481                 // one more normal
5482                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5483
5484                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5485                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5486                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5487                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5488                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5489         }
5490         else
5491         {
5492                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5493                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5494                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5495                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5496                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5497                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5498                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5499                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5500                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5501                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5502         }
5503         r_refdef.view.numfrustumplanes = 5;
5504
5505         if (r_refdef.view.useclipplane)
5506         {
5507                 r_refdef.view.numfrustumplanes = 6;
5508                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5509         }
5510
5511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5512                 PlaneClassify(r_refdef.view.frustum + i);
5513
5514         // LordHavoc: note to all quake engine coders, Quake had a special case
5515         // for 90 degrees which assumed a square view (wrong), so I removed it,
5516         // Quake2 has it disabled as well.
5517
5518         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5519         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5520         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5521         //PlaneClassify(&frustum[0]);
5522
5523         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5524         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5525         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5526         //PlaneClassify(&frustum[1]);
5527
5528         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5529         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5530         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5531         //PlaneClassify(&frustum[2]);
5532
5533         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5534         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5535         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5536         //PlaneClassify(&frustum[3]);
5537
5538         // nearclip plane
5539         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5540         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5541         //PlaneClassify(&frustum[4]);
5542 }
5543
5544 static void R_View_UpdateWithScissor(const int *myscissor)
5545 {
5546         R_Main_ResizeViewCache();
5547         R_View_SetFrustum(myscissor);
5548         R_View_WorldVisibility(r_refdef.view.useclipplane);
5549         R_View_UpdateEntityVisible();
5550 }
5551
5552 static void R_View_Update(void)
5553 {
5554         R_Main_ResizeViewCache();
5555         R_View_SetFrustum(NULL);
5556         R_View_WorldVisibility(r_refdef.view.useclipplane);
5557         R_View_UpdateEntityVisible();
5558 }
5559
5560 float viewscalefpsadjusted = 1.0f;
5561
5562 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5563 {
5564         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5565         scale = bound(0.03125f, scale, 1.0f);
5566         *outwidth = (int)ceil(width * scale);
5567         *outheight = (int)ceil(height * scale);
5568 }
5569
5570 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5571 {
5572         const float *customclipplane = NULL;
5573         float plane[4];
5574         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5575         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5576         {
5577                 // LordHavoc: couldn't figure out how to make this approach the
5578                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5579                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5580                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5581                         dist = r_refdef.view.clipplane.dist;
5582                 plane[0] = r_refdef.view.clipplane.normal[0];
5583                 plane[1] = r_refdef.view.clipplane.normal[1];
5584                 plane[2] = r_refdef.view.clipplane.normal[2];
5585                 plane[3] = -dist;
5586                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5587         }
5588
5589         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5590         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5591
5592         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5593         if (!r_refdef.view.useperspective)
5594                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5595         else if (vid.stencil && r_useinfinitefarclip.integer)
5596                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5597         else
5598                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5599         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5600         R_SetViewport(&r_refdef.view.viewport);
5601         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5602         {
5603                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5604                 float screenplane[4];
5605                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5606                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5607                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5608                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5609                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5610         }
5611 }
5612
5613 void R_EntityMatrix(const matrix4x4_t *matrix)
5614 {
5615         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5616         {
5617                 gl_modelmatrixchanged = false;
5618                 gl_modelmatrix = *matrix;
5619                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5620                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5621                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5622                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5623                 CHECKGLERROR
5624                 switch(vid.renderpath)
5625                 {
5626                 case RENDERPATH_D3D9:
5627 #ifdef SUPPORTD3D
5628                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5629                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5630 #endif
5631                         break;
5632                 case RENDERPATH_D3D10:
5633                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5634                         break;
5635                 case RENDERPATH_D3D11:
5636                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5637                         break;
5638                 case RENDERPATH_GL11:
5639                 case RENDERPATH_GL13:
5640                 case RENDERPATH_GLES1:
5641 #ifndef USE_GLES2
5642                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5643 #endif
5644                         break;
5645                 case RENDERPATH_SOFT:
5646                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5647                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5648                         break;
5649                 case RENDERPATH_GL20:
5650                 case RENDERPATH_GLES2:
5651                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5652                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5653                         break;
5654                 }
5655         }
5656 }
5657
5658 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5659 {
5660         r_viewport_t viewport;
5661
5662         CHECKGLERROR
5663
5664         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5665         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5666         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5667         R_SetViewport(&viewport);
5668         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5669         GL_Color(1, 1, 1, 1);
5670         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5671         GL_BlendFunc(GL_ONE, GL_ZERO);
5672         GL_ScissorTest(false);
5673         GL_DepthMask(false);
5674         GL_DepthRange(0, 1);
5675         GL_DepthTest(false);
5676         GL_DepthFunc(GL_LEQUAL);
5677         R_EntityMatrix(&identitymatrix);
5678         R_Mesh_ResetTextureState();
5679         GL_PolygonOffset(0, 0);
5680         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5681         switch(vid.renderpath)
5682         {
5683         case RENDERPATH_GL11:
5684         case RENDERPATH_GL13:
5685         case RENDERPATH_GL20:
5686         case RENDERPATH_GLES1:
5687         case RENDERPATH_GLES2:
5688                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5689                 break;
5690         case RENDERPATH_D3D9:
5691         case RENDERPATH_D3D10:
5692         case RENDERPATH_D3D11:
5693         case RENDERPATH_SOFT:
5694                 break;
5695         }
5696         GL_CullFace(GL_NONE);
5697
5698         CHECKGLERROR
5699 }
5700
5701 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5702 {
5703         DrawQ_Finish();
5704
5705         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5706 }
5707
5708 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5709 {
5710         DrawQ_Finish();
5711
5712         R_SetupView(true, fbo, depthtexture, colortexture);
5713         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5714         GL_Color(1, 1, 1, 1);
5715         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5716         GL_BlendFunc(GL_ONE, GL_ZERO);
5717         GL_ScissorTest(true);
5718         GL_DepthMask(true);
5719         GL_DepthRange(0, 1);
5720         GL_DepthTest(true);
5721         GL_DepthFunc(GL_LEQUAL);
5722         R_EntityMatrix(&identitymatrix);
5723         R_Mesh_ResetTextureState();
5724         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5725         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5726         switch(vid.renderpath)
5727         {
5728         case RENDERPATH_GL11:
5729         case RENDERPATH_GL13:
5730         case RENDERPATH_GL20:
5731         case RENDERPATH_GLES1:
5732         case RENDERPATH_GLES2:
5733                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5734                 break;
5735         case RENDERPATH_D3D9:
5736         case RENDERPATH_D3D10:
5737         case RENDERPATH_D3D11:
5738         case RENDERPATH_SOFT:
5739                 break;
5740         }
5741         GL_CullFace(r_refdef.view.cullface_back);
5742 }
5743
5744 /*
5745 ================
5746 R_RenderView_UpdateViewVectors
5747 ================
5748 */
5749 void R_RenderView_UpdateViewVectors(void)
5750 {
5751         // break apart the view matrix into vectors for various purposes
5752         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5753         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5754         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5755         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5756         // make an inverted copy of the view matrix for tracking sprites
5757         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5758 }
5759
5760 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5761 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5762
5763 static void R_Water_StartFrame(void)
5764 {
5765         int i;
5766         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5767         r_waterstate_waterplane_t *p;
5768         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5769
5770         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5771                 return;
5772
5773         switch(vid.renderpath)
5774         {
5775         case RENDERPATH_GL20:
5776         case RENDERPATH_D3D9:
5777         case RENDERPATH_D3D10:
5778         case RENDERPATH_D3D11:
5779         case RENDERPATH_SOFT:
5780         case RENDERPATH_GLES2:
5781                 break;
5782         case RENDERPATH_GL11:
5783         case RENDERPATH_GL13:
5784         case RENDERPATH_GLES1:
5785                 return;
5786         }
5787
5788         // set waterwidth and waterheight to the water resolution that will be
5789         // used (often less than the screen resolution for faster rendering)
5790         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5791
5792         // calculate desired texture sizes
5793         // can't use water if the card does not support the texture size
5794         if (!r_water.integer || r_showsurfaces.integer)
5795                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5796         else if (vid.support.arb_texture_non_power_of_two)
5797         {
5798                 texturewidth = waterwidth;
5799                 textureheight = waterheight;
5800                 camerawidth = waterwidth;
5801                 cameraheight = waterheight;
5802         }
5803         else
5804         {
5805                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5806                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5807                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5808                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5809         }
5810
5811         // allocate textures as needed
5812         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5813         {
5814                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5815                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5816                 {
5817                         if (p->texture_refraction)
5818                                 R_FreeTexture(p->texture_refraction);
5819                         p->texture_refraction = NULL;
5820                         if (p->fbo_refraction)
5821                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5822                         p->fbo_refraction = 0;
5823                         if (p->texture_reflection)
5824                                 R_FreeTexture(p->texture_reflection);
5825                         p->texture_reflection = NULL;
5826                         if (p->fbo_reflection)
5827                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5828                         p->fbo_reflection = 0;
5829                         if (p->texture_camera)
5830                                 R_FreeTexture(p->texture_camera);
5831                         p->texture_camera = NULL;
5832                         if (p->fbo_camera)
5833                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5834                         p->fbo_camera = 0;
5835                 }
5836                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5837                 r_fb.water.texturewidth = texturewidth;
5838                 r_fb.water.textureheight = textureheight;
5839                 r_fb.water.camerawidth = camerawidth;
5840                 r_fb.water.cameraheight = cameraheight;
5841         }
5842
5843         if (r_fb.water.texturewidth)
5844         {
5845                 int scaledwidth, scaledheight;
5846
5847                 r_fb.water.enabled = true;
5848
5849                 // water resolution is usually reduced
5850                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5851                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5852                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5853
5854                 // set up variables that will be used in shader setup
5855                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5856                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5857                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5858                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5859         }
5860
5861         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5862         r_fb.water.numwaterplanes = 0;
5863 }
5864
5865 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5866 {
5867         int planeindex, bestplaneindex, vertexindex;
5868         vec3_t mins, maxs, normal, center, v, n;
5869         vec_t planescore, bestplanescore;
5870         mplane_t plane;
5871         r_waterstate_waterplane_t *p;
5872         texture_t *t = R_GetCurrentTexture(surface->texture);
5873
5874         rsurface.texture = t;
5875         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5876         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5877         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5878                 return;
5879         // average the vertex normals, find the surface bounds (after deformvertexes)
5880         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5881         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5882         VectorCopy(n, normal);
5883         VectorCopy(v, mins);
5884         VectorCopy(v, maxs);
5885         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5886         {
5887                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5888                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5889                 VectorAdd(normal, n, normal);
5890                 mins[0] = min(mins[0], v[0]);
5891                 mins[1] = min(mins[1], v[1]);
5892                 mins[2] = min(mins[2], v[2]);
5893                 maxs[0] = max(maxs[0], v[0]);
5894                 maxs[1] = max(maxs[1], v[1]);
5895                 maxs[2] = max(maxs[2], v[2]);
5896         }
5897         VectorNormalize(normal);
5898         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5899
5900         VectorCopy(normal, plane.normal);
5901         VectorNormalize(plane.normal);
5902         plane.dist = DotProduct(center, plane.normal);
5903         PlaneClassify(&plane);
5904         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5905         {
5906                 // skip backfaces (except if nocullface is set)
5907 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5908 //                      return;
5909                 VectorNegate(plane.normal, plane.normal);
5910                 plane.dist *= -1;
5911                 PlaneClassify(&plane);
5912         }
5913
5914
5915         // find a matching plane if there is one
5916         bestplaneindex = -1;
5917         bestplanescore = 1048576.0f;
5918         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5919         {
5920                 if(p->camera_entity == t->camera_entity)
5921                 {
5922                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5923                         if (bestplaneindex < 0 || bestplanescore > planescore)
5924                         {
5925                                 bestplaneindex = planeindex;
5926                                 bestplanescore = planescore;
5927                         }
5928                 }
5929         }
5930         planeindex = bestplaneindex;
5931
5932         // if this surface does not fit any known plane rendered this frame, add one
5933         if (planeindex < 0 || bestplanescore > 0.001f)
5934         {
5935                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5936                 {
5937                         // store the new plane
5938                         planeindex = r_fb.water.numwaterplanes++;
5939                         p = r_fb.water.waterplanes + planeindex;
5940                         p->plane = plane;
5941                         // clear materialflags and pvs
5942                         p->materialflags = 0;
5943                         p->pvsvalid = false;
5944                         p->camera_entity = t->camera_entity;
5945                         VectorCopy(mins, p->mins);
5946                         VectorCopy(maxs, p->maxs);
5947                 }
5948                 else
5949                 {
5950                         // We're totally screwed.
5951                         return;
5952                 }
5953         }
5954         else
5955         {
5956                 // merge mins/maxs when we're adding this surface to the plane
5957                 p = r_fb.water.waterplanes + planeindex;
5958                 p->mins[0] = min(p->mins[0], mins[0]);
5959                 p->mins[1] = min(p->mins[1], mins[1]);
5960                 p->mins[2] = min(p->mins[2], mins[2]);
5961                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5962                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5963                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5964         }
5965         // merge this surface's materialflags into the waterplane
5966         p->materialflags |= t->currentmaterialflags;
5967         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5968         {
5969                 // merge this surface's PVS into the waterplane
5970                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5971                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5972                 {
5973                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5974                         p->pvsvalid = true;
5975                 }
5976         }
5977 }
5978
5979 extern cvar_t r_drawparticles;
5980 extern cvar_t r_drawdecals;
5981
5982 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5983 {
5984         int myscissor[4];
5985         r_refdef_view_t originalview;
5986         r_refdef_view_t myview;
5987         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;
5988         r_waterstate_waterplane_t *p;
5989         vec3_t visorigin;
5990         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5991         char vabuf[1024];
5992
5993         originalview = r_refdef.view;
5994
5995         // lowquality hack, temporarily shut down some cvars and restore afterwards
5996         qualityreduction = r_water_lowquality.integer;
5997         if (qualityreduction > 0)
5998         {
5999                 if (qualityreduction >= 1)
6000                 {
6001                         old_r_shadows = r_shadows.integer;
6002                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6003                         old_r_dlight = r_shadow_realtime_dlight.integer;
6004                         Cvar_SetValueQuick(&r_shadows, 0);
6005                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6006                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6007                 }
6008                 if (qualityreduction >= 2)
6009                 {
6010                         old_r_dynamic = r_dynamic.integer;
6011                         old_r_particles = r_drawparticles.integer;
6012                         old_r_decals = r_drawdecals.integer;
6013                         Cvar_SetValueQuick(&r_dynamic, 0);
6014                         Cvar_SetValueQuick(&r_drawparticles, 0);
6015                         Cvar_SetValueQuick(&r_drawdecals, 0);
6016                 }
6017         }
6018
6019         // make sure enough textures are allocated
6020         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6021         {
6022                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6023                         continue;
6024                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6025                 {
6026                         if (!p->texture_refraction)
6027                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6028                         if (!p->texture_refraction)
6029                                 goto error;
6030                         if (usewaterfbo)
6031                         {
6032                                 if (r_fb.water.depthtexture == NULL)
6033                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034                                 if (p->fbo_refraction == 0)
6035                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6036                         }
6037                 }
6038                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6039                 {
6040                         if (!p->texture_camera)
6041                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6042                         if (!p->texture_camera)
6043                                 goto error;
6044                         if (usewaterfbo)
6045                         {
6046                                 if (r_fb.water.depthtexture == NULL)
6047                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6048                                 if (p->fbo_camera == 0)
6049                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6050                         }
6051                 }
6052
6053                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6054                 {
6055                         if (!p->texture_reflection)
6056                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6057                         if (!p->texture_reflection)
6058                                 goto error;
6059                         if (usewaterfbo)
6060                         {
6061                                 if (r_fb.water.depthtexture == NULL)
6062                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6063                                 if (p->fbo_reflection == 0)
6064                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6065                         }
6066                 }
6067         }
6068
6069         // render views
6070         r_refdef.view = originalview;
6071         r_refdef.view.showdebug = false;
6072         r_refdef.view.width = r_fb.water.waterwidth;
6073         r_refdef.view.height = r_fb.water.waterheight;
6074         r_refdef.view.useclipplane = true;
6075         myview = r_refdef.view;
6076         r_fb.water.renderingscene = true;
6077         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078         {
6079                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6080                         continue;
6081                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6082                 {
6083                         r_refdef.view = myview;
6084                         if(r_water_scissormode.integer)
6085                         {
6086                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6087                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6088                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6089                         }
6090
6091                         // render reflected scene and copy into texture
6092                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6093                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6094                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6095                         r_refdef.view.clipplane = p->plane;
6096                         // reverse the cullface settings for this render
6097                         r_refdef.view.cullface_front = GL_FRONT;
6098                         r_refdef.view.cullface_back = GL_BACK;
6099                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6100                         {
6101                                 r_refdef.view.usecustompvs = true;
6102                                 if (p->pvsvalid)
6103                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6104                                 else
6105                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6106                         }
6107
6108                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6109                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6110                         R_ClearScreen(r_refdef.fogenabled);
6111                         if(r_water_scissormode.integer & 2)
6112                                 R_View_UpdateWithScissor(myscissor);
6113                         else
6114                                 R_View_Update();
6115                         R_AnimCache_CacheVisibleEntities();
6116                         if(r_water_scissormode.integer & 1)
6117                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6118                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6119
6120                         if (!p->fbo_reflection)
6121                                 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6122                         r_fb.water.hideplayer = false;
6123                 }
6124
6125                 // render the normal view scene and copy into texture
6126                 // (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)
6127                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6128                 {
6129                         r_refdef.view = myview;
6130                         if(r_water_scissormode.integer)
6131                         {
6132                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6133                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6134                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6135                         }
6136
6137                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6138
6139                         r_refdef.view.clipplane = p->plane;
6140                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6141                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6142
6143                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6144                         {
6145                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6146                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6147                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6148                                 R_RenderView_UpdateViewVectors();
6149                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6150                                 {
6151                                         r_refdef.view.usecustompvs = true;
6152                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6153                                 }
6154                         }
6155
6156                         PlaneClassify(&r_refdef.view.clipplane);
6157
6158                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6159                         R_ClearScreen(r_refdef.fogenabled);
6160                         if(r_water_scissormode.integer & 2)
6161                                 R_View_UpdateWithScissor(myscissor);
6162                         else
6163                                 R_View_Update();
6164                         R_AnimCache_CacheVisibleEntities();
6165                         if(r_water_scissormode.integer & 1)
6166                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6167                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6168
6169                         if (!p->fbo_refraction)
6170                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6171                         r_fb.water.hideplayer = false;
6172                 }
6173                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6174                 {
6175                         r_refdef.view = myview;
6176
6177                         r_refdef.view.clipplane = p->plane;
6178                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6179                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6180
6181                         r_refdef.view.width = r_fb.water.camerawidth;
6182                         r_refdef.view.height = r_fb.water.cameraheight;
6183                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6184                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6185                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6186                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6187
6188                         if(p->camera_entity)
6189                         {
6190                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6191                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6192                         }
6193
6194                         // note: all of the view is used for displaying... so
6195                         // there is no use in scissoring
6196
6197                         // reverse the cullface settings for this render
6198                         r_refdef.view.cullface_front = GL_FRONT;
6199                         r_refdef.view.cullface_back = GL_BACK;
6200                         // also reverse the view matrix
6201                         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
6202                         R_RenderView_UpdateViewVectors();
6203                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6204                         {
6205                                 r_refdef.view.usecustompvs = true;
6206                                 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);
6207                         }
6208                         
6209                         // camera needs no clipplane
6210                         r_refdef.view.useclipplane = false;
6211
6212                         PlaneClassify(&r_refdef.view.clipplane);
6213
6214                         r_fb.water.hideplayer = false;
6215
6216                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6217                         R_ClearScreen(r_refdef.fogenabled);
6218                         R_View_Update();
6219                         R_AnimCache_CacheVisibleEntities();
6220                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6221
6222                         if (!p->fbo_camera)
6223                                 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6224                         r_fb.water.hideplayer = false;
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);
6232         if (!r_fb.water.depthtexture)
6233                 R_ClearScreen(r_refdef.fogenabled);
6234         R_View_Update();
6235         R_AnimCache_CacheVisibleEntities();
6236         goto finish;
6237 error:
6238         r_refdef.view = originalview;
6239         r_fb.water.renderingscene = false;
6240         Cvar_SetValueQuick(&r_water, 0);
6241         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6242 finish:
6243         // lowquality hack, restore cvars
6244         if (qualityreduction > 0)
6245         {
6246                 if (qualityreduction >= 1)
6247                 {
6248                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6249                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6250                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6251                 }
6252                 if (qualityreduction >= 2)
6253                 {
6254                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6255                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6256                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6257                 }
6258         }
6259 }
6260
6261 static void R_Bloom_StartFrame(void)
6262 {
6263         int i;
6264         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6265         int viewwidth, viewheight;
6266         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6267         textype_t textype = TEXTYPE_COLORBUFFER;
6268
6269         switch (vid.renderpath)
6270         {
6271         case RENDERPATH_GL20:
6272                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6274                 {
6275                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6276                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6277                 }
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         switch(vid.renderpath)
6314         {
6315         case RENDERPATH_GL20:
6316         case RENDERPATH_D3D9:
6317         case RENDERPATH_D3D10:
6318         case RENDERPATH_D3D11:
6319         case RENDERPATH_SOFT:
6320         case RENDERPATH_GLES2:
6321                 break;
6322         case RENDERPATH_GL11:
6323         case RENDERPATH_GL13:
6324         case RENDERPATH_GLES1:
6325                 return;
6326         }
6327
6328         // set bloomwidth and bloomheight to the bloom resolution that will be
6329         // used (often less than the screen resolution for faster rendering)
6330         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6331         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6332         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6333         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6334         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6335
6336         // calculate desired texture sizes
6337         if (vid.support.arb_texture_non_power_of_two)
6338         {
6339                 screentexturewidth = vid.width;
6340                 screentextureheight = vid.height;
6341                 bloomtexturewidth = r_fb.bloomwidth;
6342                 bloomtextureheight = r_fb.bloomheight;
6343         }
6344         else
6345         {
6346                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6347                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6348                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6349                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6350         }
6351
6352         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))
6353         {
6354                 Cvar_SetValueQuick(&r_bloom, 0);
6355                 Cvar_SetValueQuick(&r_motionblur, 0);
6356                 Cvar_SetValueQuick(&r_damageblur, 0);
6357         }
6358
6359         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6360          && !r_bloom.integer
6361          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6362          && !useviewfbo
6363          && r_viewscale.value == 1.0f
6364          && !r_viewscale_fpsscaling.integer)
6365                 screentexturewidth = screentextureheight = 0;
6366         if (!r_bloom.integer)
6367                 bloomtexturewidth = bloomtextureheight = 0;
6368
6369         // allocate textures as needed
6370         if (r_fb.screentexturewidth != screentexturewidth
6371          || r_fb.screentextureheight != screentextureheight
6372          || r_fb.bloomtexturewidth != bloomtexturewidth
6373          || r_fb.bloomtextureheight != bloomtextureheight
6374          || r_fb.textype != textype
6375          || useviewfbo != (r_fb.fbo != 0))
6376         {
6377                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6378                 {
6379                         if (r_fb.bloomtexture[i])
6380                                 R_FreeTexture(r_fb.bloomtexture[i]);
6381                         r_fb.bloomtexture[i] = NULL;
6382
6383                         if (r_fb.bloomfbo[i])
6384                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6385                         r_fb.bloomfbo[i] = 0;
6386                 }
6387
6388                 if (r_fb.fbo)
6389                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6390                 r_fb.fbo = 0;
6391
6392                 if (r_fb.colortexture)
6393                         R_FreeTexture(r_fb.colortexture);
6394                 r_fb.colortexture = NULL;
6395
6396                 if (r_fb.depthtexture)
6397                         R_FreeTexture(r_fb.depthtexture);
6398                 r_fb.depthtexture = NULL;
6399
6400                 if (r_fb.ghosttexture)
6401                         R_FreeTexture(r_fb.ghosttexture);
6402                 r_fb.ghosttexture = NULL;
6403
6404                 r_fb.screentexturewidth = screentexturewidth;
6405                 r_fb.screentextureheight = screentextureheight;
6406                 r_fb.bloomtexturewidth = bloomtexturewidth;
6407                 r_fb.bloomtextureheight = bloomtextureheight;
6408                 r_fb.textype = textype;
6409
6410                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6411                 {
6412                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6413                                 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);
6414                         r_fb.ghosttexture_valid = false;
6415                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6416                         if (useviewfbo)
6417                         {
6418                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6419                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6420                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6421                         }
6422                 }
6423
6424                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6425                 {
6426                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6427                         {
6428                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6429                                 if (useviewfbo)
6430                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6431                         }
6432                 }
6433         }
6434
6435         // bloom texture is a different resolution
6436         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6437         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6438         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6439         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6440         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6441
6442         // set up a texcoord array for the full resolution screen image
6443         // (we have to keep this around to copy back during final render)
6444         r_fb.screentexcoord2f[0] = 0;
6445         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6446         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6447         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6448         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6449         r_fb.screentexcoord2f[5] = 0;
6450         r_fb.screentexcoord2f[6] = 0;
6451         r_fb.screentexcoord2f[7] = 0;
6452
6453         if(r_fb.fbo) 
6454         {
6455                 for (i = 1;i < 8;i += 2)
6456                 {
6457                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6458                 }
6459         }
6460
6461         // set up a texcoord array for the reduced resolution bloom image
6462         // (which will be additive blended over the screen image)
6463         r_fb.bloomtexcoord2f[0] = 0;
6464         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6465         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6466         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6467         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6468         r_fb.bloomtexcoord2f[5] = 0;
6469         r_fb.bloomtexcoord2f[6] = 0;
6470         r_fb.bloomtexcoord2f[7] = 0;
6471
6472         switch(vid.renderpath)
6473         {
6474         case RENDERPATH_GL11:
6475         case RENDERPATH_GL13:
6476         case RENDERPATH_GL20:
6477         case RENDERPATH_SOFT:
6478         case RENDERPATH_GLES1:
6479         case RENDERPATH_GLES2:
6480                 break;
6481         case RENDERPATH_D3D9:
6482         case RENDERPATH_D3D10:
6483         case RENDERPATH_D3D11:
6484                 for (i = 0;i < 4;i++)
6485                 {
6486                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6487                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6488                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6489                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6490                 }
6491                 break;
6492         }
6493
6494         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6495
6496         if (r_fb.fbo)
6497                 r_refdef.view.clear = true;
6498 }
6499
6500 static void R_Bloom_MakeTexture(void)
6501 {
6502         int x, range, dir;
6503         float xoffset, yoffset, r, brighten;
6504         rtexture_t *intex;
6505         float colorscale = r_bloom_colorscale.value;
6506
6507         r_refdef.stats[r_stat_bloom]++;
6508     
6509 #if 0
6510     // this copy is unnecessary since it happens in R_BlendView already
6511         if (!r_fb.fbo)
6512         {
6513                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6514                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6515         }
6516 #endif
6517
6518         // scale down screen texture to the bloom texture size
6519         CHECKGLERROR
6520         r_fb.bloomindex = 0;
6521         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6522         R_SetViewport(&r_fb.bloomviewport);
6523         GL_CullFace(GL_NONE);
6524         GL_DepthTest(false);
6525         GL_BlendFunc(GL_ONE, GL_ZERO);
6526         GL_Color(colorscale, colorscale, colorscale, 1);
6527         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6528         switch(vid.renderpath)
6529         {
6530         case RENDERPATH_GL11:
6531         case RENDERPATH_GL13:
6532         case RENDERPATH_GL20:
6533         case RENDERPATH_GLES1:
6534         case RENDERPATH_GLES2:
6535         case RENDERPATH_SOFT:
6536                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6537                 break;
6538         case RENDERPATH_D3D9:
6539         case RENDERPATH_D3D10:
6540         case RENDERPATH_D3D11:
6541                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6542                 break;
6543         }
6544         // TODO: do boxfilter scale-down in shader?
6545         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6546         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6548
6549         // we now have a properly scaled bloom image
6550         if (!r_fb.bloomfbo[r_fb.bloomindex])
6551         {
6552                 // copy it into the bloom texture
6553                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6554                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6555         }
6556
6557         // multiply bloom image by itself as many times as desired
6558         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6559         {
6560                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6561                 r_fb.bloomindex ^= 1;
6562                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6563                 x *= 2;
6564                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6565                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6566                 {
6567                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6568                         GL_Color(r,r,r,1); // apply fix factor
6569                 }
6570                 else
6571                 {
6572                         if(x <= 2)
6573                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6574                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6575                         GL_Color(1,1,1,1); // no fix factor supported here
6576                 }
6577                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6578                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6579                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6580                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6581
6582                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6583                 {
6584                         // copy the darkened image to a texture
6585                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6586                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6587                 }
6588         }
6589
6590         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6591         brighten = r_bloom_brighten.value;
6592         brighten = sqrt(brighten);
6593         if(range >= 1)
6594                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6595
6596         for (dir = 0;dir < 2;dir++)
6597         {
6598                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6599                 r_fb.bloomindex ^= 1;
6600                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6601                 // blend on at multiple vertical offsets to achieve a vertical blur
6602                 // TODO: do offset blends using GLSL
6603                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6604                 GL_BlendFunc(GL_ONE, GL_ZERO);
6605                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6606                 for (x = -range;x <= range;x++)
6607                 {
6608                         if (!dir){xoffset = 0;yoffset = x;}
6609                         else {xoffset = x;yoffset = 0;}
6610                         xoffset /= (float)r_fb.bloomtexturewidth;
6611                         yoffset /= (float)r_fb.bloomtextureheight;
6612                         // compute a texcoord array with the specified x and y offset
6613                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6614                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6615                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6616                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6617                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6618                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6619                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6620                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6621                         // this r value looks like a 'dot' particle, fading sharply to
6622                         // black at the edges
6623                         // (probably not realistic but looks good enough)
6624                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6625                         //r = brighten/(range*2+1);
6626                         r = brighten / (range * 2 + 1);
6627                         if(range >= 1)
6628                                 r *= (1 - x*x/(float)(range*range));
6629                         GL_Color(r, r, r, 1);
6630                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6631                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6632                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6633                         GL_BlendFunc(GL_ONE, GL_ONE);
6634                 }
6635
6636                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6637                 {
6638                         // copy the vertically or horizontally blurred bloom view to a texture
6639                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6640                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6641                 }
6642         }
6643 }
6644
6645 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6646 {
6647         dpuint64 permutation;
6648         float uservecs[4][4];
6649
6650         R_EntityMatrix(&identitymatrix);
6651
6652         switch (vid.renderpath)
6653         {
6654         case RENDERPATH_GL20:
6655         case RENDERPATH_D3D9:
6656         case RENDERPATH_D3D10:
6657         case RENDERPATH_D3D11:
6658         case RENDERPATH_SOFT:
6659         case RENDERPATH_GLES2:
6660                 permutation =
6661                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6662                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6663                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6664                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6665                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6666
6667                 if (r_fb.colortexture)
6668                 {
6669                         if (!r_fb.fbo)
6670                         {
6671                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6672                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6673                         }
6674
6675                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6676                         {
6677                                 // declare variables
6678                                 float blur_factor, blur_mouseaccel, blur_velocity;
6679                                 static float blur_average; 
6680                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6681
6682                                 // set a goal for the factoring
6683                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6684                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6685                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6686                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6687                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6688                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6689
6690                                 // from the goal, pick an averaged value between goal and last value
6691                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6692                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6693
6694                                 // enforce minimum amount of blur 
6695                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6696
6697                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6698
6699                                 // calculate values into a standard alpha
6700                                 cl.motionbluralpha = 1 - exp(-
6701                                                 (
6702                                                  (r_motionblur.value * blur_factor / 80)
6703                                                  +
6704                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6705                                                 )
6706                                                 /
6707                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6708                                           );
6709
6710                                 // randomization for the blur value to combat persistent ghosting
6711                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6712                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6713
6714                                 // apply the blur
6715                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6716                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6717                                 {
6718                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6720                                         switch(vid.renderpath)
6721                                         {
6722                                         case RENDERPATH_GL11:
6723                                         case RENDERPATH_GL13:
6724                                         case RENDERPATH_GL20:
6725                                         case RENDERPATH_GLES1:
6726                                         case RENDERPATH_GLES2:
6727                                         case RENDERPATH_SOFT:
6728                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6729                                                 break;
6730                                         case RENDERPATH_D3D9:
6731                                         case RENDERPATH_D3D10:
6732                                         case RENDERPATH_D3D11:
6733                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6734                                                 break;
6735                                         }
6736                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6737                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6738                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6739                                 }
6740
6741                                 // updates old view angles for next pass
6742                                 VectorCopy(cl.viewangles, blur_oldangles);
6743
6744                                 // copy view into the ghost texture
6745                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6746                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6747                                 r_fb.ghosttexture_valid = true;
6748                         }
6749                 }
6750                 else
6751                 {
6752                         // no r_fb.colortexture means we're rendering to the real fb
6753                         // we may still have to do view tint...
6754                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6755                         {
6756                                 // apply a color tint to the whole view
6757                                 R_ResetViewRendering2D(0, NULL, NULL);
6758                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6759                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6760                                 R_SetupShader_Generic_NoTexture(false, true);
6761                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6762                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6763                         }
6764                         break; // no screen processing, no bloom, skip it
6765                 }
6766
6767                 if (r_fb.bloomtexture[0])
6768                 {
6769                         // make the bloom texture
6770                         R_Bloom_MakeTexture();
6771                 }
6772
6773 #if _MSC_VER >= 1400
6774 #define sscanf sscanf_s
6775 #endif
6776                 memset(uservecs, 0, sizeof(uservecs));
6777                 if (r_glsl_postprocess_uservec1_enable.integer)
6778                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6779                 if (r_glsl_postprocess_uservec2_enable.integer)
6780                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6781                 if (r_glsl_postprocess_uservec3_enable.integer)
6782                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6783                 if (r_glsl_postprocess_uservec4_enable.integer)
6784                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6785
6786                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6787                 GL_Color(1, 1, 1, 1);
6788                 GL_BlendFunc(GL_ONE, GL_ZERO);
6789
6790                 switch(vid.renderpath)
6791                 {
6792                 case RENDERPATH_GL20:
6793                 case RENDERPATH_GLES2:
6794                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6796                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6797                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6798                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6799                         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]);
6800                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801                         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]);
6802                         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]);
6803                         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]);
6804                         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]);
6805                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6806                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6807                         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);
6808                         break;
6809                 case RENDERPATH_D3D9:
6810 #ifdef SUPPORTD3D
6811                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6812                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6813                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6814                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6815                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6816                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6817                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6818                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6819                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6820                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6821                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6822                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6823                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6824                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6825                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6826 #endif
6827                         break;
6828                 case RENDERPATH_D3D10:
6829                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6830                         break;
6831                 case RENDERPATH_D3D11:
6832                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6833                         break;
6834                 case RENDERPATH_SOFT:
6835                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6836                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6837                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6838                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6839                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6840                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6841                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6842                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6843                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6844                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6845                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6846                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6847                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6848                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6849                         break;
6850                 default:
6851                         break;
6852                 }
6853                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6855                 break;
6856         case RENDERPATH_GL11:
6857         case RENDERPATH_GL13:
6858         case RENDERPATH_GLES1:
6859                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6860                 {
6861                         // apply a color tint to the whole view
6862                         R_ResetViewRendering2D(0, NULL, NULL);
6863                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865                         R_SetupShader_Generic_NoTexture(false, true);
6866                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6868                 }
6869                 break;
6870         }
6871 }
6872
6873 matrix4x4_t r_waterscrollmatrix;
6874
6875 void R_UpdateFog(void)
6876 {
6877         // Nehahra fog
6878         if (gamemode == GAME_NEHAHRA)
6879         {
6880                 if (gl_fogenable.integer)
6881                 {
6882                         r_refdef.oldgl_fogenable = true;
6883                         r_refdef.fog_density = gl_fogdensity.value;
6884                         r_refdef.fog_red = gl_fogred.value;
6885                         r_refdef.fog_green = gl_foggreen.value;
6886                         r_refdef.fog_blue = gl_fogblue.value;
6887                         r_refdef.fog_alpha = 1;
6888                         r_refdef.fog_start = 0;
6889                         r_refdef.fog_end = gl_skyclip.value;
6890                         r_refdef.fog_height = 1<<30;
6891                         r_refdef.fog_fadedepth = 128;
6892                 }
6893                 else if (r_refdef.oldgl_fogenable)
6894                 {
6895                         r_refdef.oldgl_fogenable = false;
6896                         r_refdef.fog_density = 0;
6897                         r_refdef.fog_red = 0;
6898                         r_refdef.fog_green = 0;
6899                         r_refdef.fog_blue = 0;
6900                         r_refdef.fog_alpha = 0;
6901                         r_refdef.fog_start = 0;
6902                         r_refdef.fog_end = 0;
6903                         r_refdef.fog_height = 1<<30;
6904                         r_refdef.fog_fadedepth = 128;
6905                 }
6906         }
6907
6908         // fog parms
6909         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6910         r_refdef.fog_start = max(0, r_refdef.fog_start);
6911         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6912
6913         if (r_refdef.fog_density && r_drawfog.integer)
6914         {
6915                 r_refdef.fogenabled = true;
6916                 // this is the point where the fog reaches 0.9986 alpha, which we
6917                 // consider a good enough cutoff point for the texture
6918                 // (0.9986 * 256 == 255.6)
6919                 if (r_fog_exp2.integer)
6920                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6921                 else
6922                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6923                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6924                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6925                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6926                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6927                         R_BuildFogHeightTexture();
6928                 // fog color was already set
6929                 // update the fog texture
6930                 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)
6931                         R_BuildFogTexture();
6932                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6933                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6934         }
6935         else
6936                 r_refdef.fogenabled = false;
6937
6938         // fog color
6939         if (r_refdef.fog_density)
6940         {
6941                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6942                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6943                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6944
6945                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6946                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6947                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6948                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6949
6950                 {
6951                         vec3_t fogvec;
6952                         VectorCopy(r_refdef.fogcolor, fogvec);
6953                         //   color.rgb *= ContrastBoost * SceneBrightness;
6954                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6955                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6956                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6957                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6958                 }
6959         }
6960 }
6961
6962 void R_UpdateVariables(void)
6963 {
6964         R_Textures_Frame();
6965
6966         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6967
6968         r_refdef.farclip = r_farclip_base.value;
6969         if (r_refdef.scene.worldmodel)
6970                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6971         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6972
6973         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6974                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6975         r_refdef.polygonfactor = 0;
6976         r_refdef.polygonoffset = 0;
6977         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6978         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6979
6980         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6981         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6982         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6983         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6984         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6985         if (FAKELIGHT_ENABLED)
6986         {
6987                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6988         }
6989         else if (r_refdef.scene.worldmodel)
6990         {
6991                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6992         }
6993         if (r_showsurfaces.integer)
6994         {
6995                 r_refdef.scene.rtworld = false;
6996                 r_refdef.scene.rtworldshadows = false;
6997                 r_refdef.scene.rtdlight = false;
6998                 r_refdef.scene.rtdlightshadows = false;
6999                 r_refdef.scene.lightmapintensity = 0;
7000         }
7001
7002         r_gpuskeletal = false;
7003         switch(vid.renderpath)
7004         {
7005         case RENDERPATH_GL20:
7006                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7007         case RENDERPATH_D3D9:
7008         case RENDERPATH_D3D10:
7009         case RENDERPATH_D3D11:
7010         case RENDERPATH_SOFT:
7011         case RENDERPATH_GLES2:
7012                 if(!vid_gammatables_trivial)
7013                 {
7014                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7015                         {
7016                                 // build GLSL gamma texture
7017 #define RAMPWIDTH 256
7018                                 unsigned short ramp[RAMPWIDTH * 3];
7019                                 unsigned char rampbgr[RAMPWIDTH][4];
7020                                 int i;
7021
7022                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7023
7024                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7025                                 for(i = 0; i < RAMPWIDTH; ++i)
7026                                 {
7027                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7028                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7029                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7030                                         rampbgr[i][3] = 0;
7031                                 }
7032                                 if (r_texture_gammaramps)
7033                                 {
7034                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7035                                 }
7036                                 else
7037                                 {
7038                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7039                                 }
7040                         }
7041                 }
7042                 else
7043                 {
7044                         // remove GLSL gamma texture
7045                 }
7046                 break;
7047         case RENDERPATH_GL11:
7048         case RENDERPATH_GL13:
7049         case RENDERPATH_GLES1:
7050                 break;
7051         }
7052 }
7053
7054 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7055 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7056 /*
7057 ================
7058 R_SelectScene
7059 ================
7060 */
7061 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7062         if( scenetype != r_currentscenetype ) {
7063                 // store the old scenetype
7064                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7065                 r_currentscenetype = scenetype;
7066                 // move in the new scene
7067                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7068         }
7069 }
7070
7071 /*
7072 ================
7073 R_GetScenePointer
7074 ================
7075 */
7076 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7077 {
7078         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7079         if( scenetype == r_currentscenetype ) {
7080                 return &r_refdef.scene;
7081         } else {
7082                 return &r_scenes_store[ scenetype ];
7083         }
7084 }
7085
7086 static int R_SortEntities_Compare(const void *ap, const void *bp)
7087 {
7088         const entity_render_t *a = *(const entity_render_t **)ap;
7089         const entity_render_t *b = *(const entity_render_t **)bp;
7090
7091         // 1. compare model
7092         if(a->model < b->model)
7093                 return -1;
7094         if(a->model > b->model)
7095                 return +1;
7096
7097         // 2. compare skin
7098         // TODO possibly calculate the REAL skinnum here first using
7099         // skinscenes?
7100         if(a->skinnum < b->skinnum)
7101                 return -1;
7102         if(a->skinnum > b->skinnum)
7103                 return +1;
7104
7105         // everything we compared is equal
7106         return 0;
7107 }
7108 static void R_SortEntities(void)
7109 {
7110         // below or equal 2 ents, sorting never gains anything
7111         if(r_refdef.scene.numentities <= 2)
7112                 return;
7113         // sort
7114         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7115 }
7116
7117 /*
7118 ================
7119 R_RenderView
7120 ================
7121 */
7122 int dpsoftrast_test;
7123 extern cvar_t r_shadow_bouncegrid;
7124 void R_RenderView(void)
7125 {
7126         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7127         int fbo;
7128         rtexture_t *depthtexture;
7129         rtexture_t *colortexture;
7130
7131         dpsoftrast_test = r_test.integer;
7132
7133         if (r_timereport_active)
7134                 R_TimeReport("start");
7135         r_textureframe++; // used only by R_GetCurrentTexture
7136         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7137
7138         if(R_CompileShader_CheckStaticParms())
7139                 R_GLSL_Restart_f();
7140
7141         if (!r_drawentities.integer)
7142                 r_refdef.scene.numentities = 0;
7143         else if (r_sortentities.integer)
7144                 R_SortEntities();
7145
7146         R_AnimCache_ClearCache();
7147
7148         /* adjust for stereo display */
7149         if(R_Stereo_Active())
7150         {
7151                 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);
7152                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7153         }
7154
7155         if (r_refdef.view.isoverlay)
7156         {
7157                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7158                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7159                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7160                 R_TimeReport("depthclear");
7161
7162                 r_refdef.view.showdebug = false;
7163
7164                 r_fb.water.enabled = false;
7165                 r_fb.water.numwaterplanes = 0;
7166
7167                 R_RenderScene(0, NULL, NULL);
7168
7169                 r_refdef.view.matrix = originalmatrix;
7170
7171                 CHECKGLERROR
7172                 return;
7173         }
7174
7175         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7176         {
7177                 r_refdef.view.matrix = originalmatrix;
7178                 return;
7179         }
7180
7181         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7182
7183         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7184                 // in sRGB fallback, behave similar to true sRGB: convert this
7185                 // value from linear to sRGB
7186                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7187
7188         R_RenderView_UpdateViewVectors();
7189
7190         R_Shadow_UpdateWorldLightSelection();
7191
7192         R_Bloom_StartFrame();
7193
7194         // apply bloom brightness offset
7195         if(r_fb.bloomtexture[0])
7196                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7197
7198         R_Water_StartFrame();
7199
7200         // now we probably have an fbo to render into
7201         fbo = r_fb.fbo;
7202         depthtexture = r_fb.depthtexture;
7203         colortexture = r_fb.colortexture;
7204
7205         CHECKGLERROR
7206         if (r_timereport_active)
7207                 R_TimeReport("viewsetup");
7208
7209         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7210
7211         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7212         {
7213                 R_ClearScreen(r_refdef.fogenabled);
7214                 if (r_timereport_active)
7215                         R_TimeReport("viewclear");
7216         }
7217         r_refdef.view.clear = true;
7218
7219         r_refdef.view.showdebug = true;
7220
7221         R_View_Update();
7222         if (r_timereport_active)
7223                 R_TimeReport("visibility");
7224
7225         R_AnimCache_CacheVisibleEntities();
7226         if (r_timereport_active)
7227                 R_TimeReport("animcache");
7228
7229         R_Shadow_UpdateBounceGridTexture();
7230         if (r_timereport_active && r_shadow_bouncegrid.integer)
7231                 R_TimeReport("bouncegrid");
7232
7233         r_fb.water.numwaterplanes = 0;
7234         if (r_fb.water.enabled)
7235                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7236
7237         R_RenderScene(fbo, depthtexture, colortexture);
7238         r_fb.water.numwaterplanes = 0;
7239
7240         R_BlendView(fbo, depthtexture, colortexture);
7241         if (r_timereport_active)
7242                 R_TimeReport("blendview");
7243
7244         GL_Scissor(0, 0, vid.width, vid.height);
7245         GL_ScissorTest(false);
7246
7247         r_refdef.view.matrix = originalmatrix;
7248
7249         CHECKGLERROR
7250 }
7251
7252 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7253 {
7254         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7255         {
7256                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7257                 if (r_timereport_active)
7258                         R_TimeReport("waterworld");
7259         }
7260
7261         // don't let sound skip if going slow
7262         if (r_refdef.scene.extraupdate)
7263                 S_ExtraUpdate ();
7264
7265         R_DrawModelsAddWaterPlanes();
7266         if (r_timereport_active)
7267                 R_TimeReport("watermodels");
7268
7269         if (r_fb.water.numwaterplanes)
7270         {
7271                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7272                 if (r_timereport_active)
7273                         R_TimeReport("waterscenes");
7274         }
7275 }
7276
7277 extern cvar_t cl_locs_show;
7278 static void R_DrawLocs(void);
7279 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7280 static void R_DrawModelDecals(void);
7281 extern cvar_t cl_decals_newsystem;
7282 extern qboolean r_shadow_usingdeferredprepass;
7283 extern int r_shadow_shadowmapatlas_modelshadows_size;
7284 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7285 {
7286         qboolean shadowmapping = false;
7287
7288         if (r_timereport_active)
7289                 R_TimeReport("beginscene");
7290
7291         r_refdef.stats[r_stat_renders]++;
7292
7293         R_UpdateFog();
7294
7295         // don't let sound skip if going slow
7296         if (r_refdef.scene.extraupdate)
7297                 S_ExtraUpdate ();
7298
7299         R_MeshQueue_BeginScene();
7300
7301         R_SkyStartFrame();
7302
7303         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);
7304
7305         if (r_timereport_active)
7306                 R_TimeReport("skystartframe");
7307
7308         if (cl.csqc_vidvars.drawworld)
7309         {
7310                 // don't let sound skip if going slow
7311                 if (r_refdef.scene.extraupdate)
7312                         S_ExtraUpdate ();
7313
7314                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7315                 {
7316                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7317                         if (r_timereport_active)
7318                                 R_TimeReport("worldsky");
7319                 }
7320
7321                 if (R_DrawBrushModelsSky() && r_timereport_active)
7322                         R_TimeReport("bmodelsky");
7323
7324                 if (skyrendermasked && skyrenderlater)
7325                 {
7326                         // we have to force off the water clipping plane while rendering sky
7327                         R_SetupView(false, fbo, depthtexture, colortexture);
7328                         R_Sky();
7329                         R_SetupView(true, fbo, depthtexture, colortexture);
7330                         if (r_timereport_active)
7331                                 R_TimeReport("sky");
7332                 }
7333         }
7334
7335         R_Shadow_PrepareModelShadows();
7336         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7337         if (r_timereport_active)
7338                 R_TimeReport("preparelights");
7339
7340         // render all the shadowmaps that will be used for this view
7341         shadowmapping = R_Shadow_ShadowMappingEnabled();
7342         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7343         {
7344                 R_Shadow_DrawShadowMaps();
7345                 if (r_timereport_active)
7346                         R_TimeReport("shadowmaps");
7347         }
7348
7349         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7350         if (r_shadow_usingdeferredprepass)
7351                 R_Shadow_DrawPrepass();
7352
7353         // now we begin the forward pass of the view render
7354         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7355         {
7356                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7357                 if (r_timereport_active)
7358                         R_TimeReport("worlddepth");
7359         }
7360         if (r_depthfirst.integer >= 2)
7361         {
7362                 R_DrawModelsDepth();
7363                 if (r_timereport_active)
7364                         R_TimeReport("modeldepth");
7365         }
7366
7367         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7368         {
7369                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7370                 if (r_timereport_active)
7371                         R_TimeReport("world");
7372         }
7373
7374         // don't let sound skip if going slow
7375         if (r_refdef.scene.extraupdate)
7376                 S_ExtraUpdate ();
7377
7378         R_DrawModels();
7379         if (r_timereport_active)
7380                 R_TimeReport("models");
7381
7382         // don't let sound skip if going slow
7383         if (r_refdef.scene.extraupdate)
7384                 S_ExtraUpdate ();
7385
7386         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7387         {
7388                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7389                 R_Shadow_DrawModelShadows();
7390                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7391                 // don't let sound skip if going slow
7392                 if (r_refdef.scene.extraupdate)
7393                         S_ExtraUpdate ();
7394         }
7395
7396         if (!r_shadow_usingdeferredprepass)
7397         {
7398                 R_Shadow_DrawLights();
7399                 if (r_timereport_active)
7400                         R_TimeReport("rtlights");
7401         }
7402
7403         // don't let sound skip if going slow
7404         if (r_refdef.scene.extraupdate)
7405                 S_ExtraUpdate ();
7406
7407         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7408         {
7409                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410                 R_Shadow_DrawModelShadows();
7411                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412                 // don't let sound skip if going slow
7413                 if (r_refdef.scene.extraupdate)
7414                         S_ExtraUpdate ();
7415         }
7416
7417         if (cl.csqc_vidvars.drawworld)
7418         {
7419                 if (cl_decals_newsystem.integer)
7420                 {
7421                         R_DrawModelDecals();
7422                         if (r_timereport_active)
7423                                 R_TimeReport("modeldecals");
7424                 }
7425                 else
7426                 {
7427                         R_DrawDecals();
7428                         if (r_timereport_active)
7429                                 R_TimeReport("decals");
7430                 }
7431
7432                 R_DrawParticles();
7433                 if (r_timereport_active)
7434                         R_TimeReport("particles");
7435
7436                 R_DrawExplosions();
7437                 if (r_timereport_active)
7438                         R_TimeReport("explosions");
7439         }
7440
7441         if (r_refdef.view.showdebug)
7442         {
7443                 if (cl_locs_show.integer)
7444                 {
7445                         R_DrawLocs();
7446                         if (r_timereport_active)
7447                                 R_TimeReport("showlocs");
7448                 }
7449
7450                 if (r_drawportals.integer)
7451                 {
7452                         R_DrawPortals();
7453                         if (r_timereport_active)
7454                                 R_TimeReport("portals");
7455                 }
7456
7457                 if (r_showbboxes_client.value > 0)
7458                 {
7459                         R_DrawEntityBBoxes(CLVM_prog);
7460                         if (r_timereport_active)
7461                                 R_TimeReport("clbboxes");
7462                 }
7463                 if (r_showbboxes.value > 0)
7464                 {
7465                         R_DrawEntityBBoxes(SVVM_prog);
7466                         if (r_timereport_active)
7467                                 R_TimeReport("svbboxes");
7468                 }
7469         }
7470
7471         if (r_transparent.integer)
7472         {
7473                 R_MeshQueue_RenderTransparent();
7474                 if (r_timereport_active)
7475                         R_TimeReport("drawtrans");
7476         }
7477
7478         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))
7479         {
7480                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7481                 if (r_timereport_active)
7482                         R_TimeReport("worlddebug");
7483                 R_DrawModelsDebug();
7484                 if (r_timereport_active)
7485                         R_TimeReport("modeldebug");
7486         }
7487
7488         if (cl.csqc_vidvars.drawworld)
7489         {
7490                 R_Shadow_DrawCoronas();
7491                 if (r_timereport_active)
7492                         R_TimeReport("coronas");
7493         }
7494
7495 #if 0
7496         {
7497                 GL_DepthTest(false);
7498                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7499                 GL_Color(1, 1, 1, 1);
7500                 qglBegin(GL_POLYGON);
7501                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7502                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7503                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7504                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7505                 qglEnd();
7506                 qglBegin(GL_POLYGON);
7507                 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]);
7508                 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]);
7509                 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]);
7510                 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]);
7511                 qglEnd();
7512                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7513         }
7514 #endif
7515
7516         // don't let sound skip if going slow
7517         if (r_refdef.scene.extraupdate)
7518                 S_ExtraUpdate ();
7519 }
7520
7521 static const unsigned short bboxelements[36] =
7522 {
7523         5, 1, 3, 5, 3, 7,
7524         6, 2, 0, 6, 0, 4,
7525         7, 3, 2, 7, 2, 6,
7526         4, 0, 1, 4, 1, 5,
7527         4, 5, 7, 4, 7, 6,
7528         1, 0, 2, 1, 2, 3,
7529 };
7530
7531 #define BBOXEDGES 13
7532 static const float bboxedges[BBOXEDGES][6] = 
7533 {
7534         // whole box
7535         { 0, 0, 0, 1, 1, 1 },
7536         // bottom edges
7537         { 0, 0, 0, 0, 1, 0 },
7538         { 0, 0, 0, 1, 0, 0 },
7539         { 0, 1, 0, 1, 1, 0 },
7540         { 1, 0, 0, 1, 1, 0 },
7541         // top edges
7542         { 0, 0, 1, 0, 1, 1 },
7543         { 0, 0, 1, 1, 0, 1 },
7544         { 0, 1, 1, 1, 1, 1 },
7545         { 1, 0, 1, 1, 1, 1 },
7546         // vertical edges
7547         { 0, 0, 0, 0, 0, 1 },
7548         { 1, 0, 0, 1, 0, 1 },
7549         { 0, 1, 0, 0, 1, 1 },
7550         { 1, 1, 0, 1, 1, 1 },
7551 };
7552
7553 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7554 {
7555         int numvertices = BBOXEDGES * 8;
7556         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7557         int numtriangles = BBOXEDGES * 12;
7558         unsigned short elements[BBOXEDGES * 36];
7559         int i, edge;
7560         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7561
7562         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7563
7564         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7565         GL_DepthMask(false);
7566         GL_DepthRange(0, 1);
7567         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7568
7569         for (edge = 0; edge < BBOXEDGES; edge++)
7570         {
7571                 for (i = 0; i < 3; i++)
7572                 {
7573                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7574                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7575                 }
7576                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7577                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7578                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7579                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7580                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7581                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7582                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7583                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7584                 for (i = 0; i < 36; i++)
7585                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7586         }
7587         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7588         if (r_refdef.fogenabled)
7589         {
7590                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7591                 {
7592                         f1 = RSurf_FogVertex(v);
7593                         f2 = 1 - f1;
7594                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7595                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7596                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7597                 }
7598         }
7599         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7600         R_Mesh_ResetTextureState();
7601         R_SetupShader_Generic_NoTexture(false, false);
7602         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7603 }
7604
7605 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7606 {
7607         // hacky overloading of the parameters
7608         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7609         int i;
7610         float color[4];
7611         prvm_edict_t *edict;
7612
7613         GL_CullFace(GL_NONE);
7614         R_SetupShader_Generic_NoTexture(false, false);
7615
7616         for (i = 0;i < numsurfaces;i++)
7617         {
7618                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7619                 switch ((int)PRVM_serveredictfloat(edict, solid))
7620                 {
7621                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7622                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7623                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7624                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7625                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7626                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7627                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7628                 }
7629                 if (prog == CLVM_prog)
7630                         color[3] *= r_showbboxes_client.value;
7631                 else
7632                         color[3] *= r_showbboxes.value;
7633                 color[3] = bound(0, color[3], 1);
7634                 GL_DepthTest(!r_showdisabledepthtest.integer);
7635                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7636         }
7637 }
7638
7639 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7640 {
7641         int i;
7642         prvm_edict_t *edict;
7643         vec3_t center;
7644
7645         if (prog == NULL)
7646                 return;
7647
7648         for (i = 0; i < prog->num_edicts; i++)
7649         {
7650                 edict = PRVM_EDICT_NUM(i);
7651                 if (edict->priv.server->free)
7652                         continue;
7653                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7654                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7655                         continue;
7656                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7657                         continue;
7658                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7659                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7660         }
7661 }
7662
7663 static const int nomodelelement3i[24] =
7664 {
7665         5, 2, 0,
7666         5, 1, 2,
7667         5, 0, 3,
7668         5, 3, 1,
7669         0, 2, 4,
7670         2, 1, 4,
7671         3, 0, 4,
7672         1, 3, 4
7673 };
7674
7675 static const unsigned short nomodelelement3s[24] =
7676 {
7677         5, 2, 0,
7678         5, 1, 2,
7679         5, 0, 3,
7680         5, 3, 1,
7681         0, 2, 4,
7682         2, 1, 4,
7683         3, 0, 4,
7684         1, 3, 4
7685 };
7686
7687 static const float nomodelvertex3f[6*3] =
7688 {
7689         -16,   0,   0,
7690          16,   0,   0,
7691           0, -16,   0,
7692           0,  16,   0,
7693           0,   0, -16,
7694           0,   0,  16
7695 };
7696
7697 static const float nomodelcolor4f[6*4] =
7698 {
7699         0.0f, 0.0f, 0.5f, 1.0f,
7700         0.0f, 0.0f, 0.5f, 1.0f,
7701         0.0f, 0.5f, 0.0f, 1.0f,
7702         0.0f, 0.5f, 0.0f, 1.0f,
7703         0.5f, 0.0f, 0.0f, 1.0f,
7704         0.5f, 0.0f, 0.0f, 1.0f
7705 };
7706
7707 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7708 {
7709         int i;
7710         float f1, f2, *c;
7711         float color4f[6*4];
7712
7713         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);
7714
7715         // this is only called once per entity so numsurfaces is always 1, and
7716         // surfacelist is always {0}, so this code does not handle batches
7717
7718         if (rsurface.ent_flags & RENDER_ADDITIVE)
7719         {
7720                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7721                 GL_DepthMask(false);
7722         }
7723         else if (ent->alpha < 1)
7724         {
7725                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7726                 GL_DepthMask(false);
7727         }
7728         else
7729         {
7730                 GL_BlendFunc(GL_ONE, GL_ZERO);
7731                 GL_DepthMask(true);
7732         }
7733         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7734         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7735         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7736         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7737         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7738         for (i = 0, c = color4f;i < 6;i++, c += 4)
7739         {
7740                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7741                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7742                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7743                 c[3] *= ent->alpha;
7744         }
7745         if (r_refdef.fogenabled)
7746         {
7747                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7748                 {
7749                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7750                         f2 = 1 - f1;
7751                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7752                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7753                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7754                 }
7755         }
7756 //      R_Mesh_ResetTextureState();
7757         R_SetupShader_Generic_NoTexture(false, false);
7758         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7759         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7760 }
7761
7762 void R_DrawNoModel(entity_render_t *ent)
7763 {
7764         vec3_t org;
7765         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7766         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7767                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7768         else
7769                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7770 }
7771
7772 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7773 {
7774         vec3_t right1, right2, diff, normal;
7775
7776         VectorSubtract (org2, org1, normal);
7777
7778         // calculate 'right' vector for start
7779         VectorSubtract (r_refdef.view.origin, org1, diff);
7780         CrossProduct (normal, diff, right1);
7781         VectorNormalize (right1);
7782
7783         // calculate 'right' vector for end
7784         VectorSubtract (r_refdef.view.origin, org2, diff);
7785         CrossProduct (normal, diff, right2);
7786         VectorNormalize (right2);
7787
7788         vert[ 0] = org1[0] + width * right1[0];
7789         vert[ 1] = org1[1] + width * right1[1];
7790         vert[ 2] = org1[2] + width * right1[2];
7791         vert[ 3] = org1[0] - width * right1[0];
7792         vert[ 4] = org1[1] - width * right1[1];
7793         vert[ 5] = org1[2] - width * right1[2];
7794         vert[ 6] = org2[0] - width * right2[0];
7795         vert[ 7] = org2[1] - width * right2[1];
7796         vert[ 8] = org2[2] - width * right2[2];
7797         vert[ 9] = org2[0] + width * right2[0];
7798         vert[10] = org2[1] + width * right2[1];
7799         vert[11] = org2[2] + width * right2[2];
7800 }
7801
7802 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)
7803 {
7804         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7805         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7806         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7807         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7808         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7809         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7810         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7811         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7812         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7813         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7814         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7815         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7816 }
7817
7818 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7819 {
7820         int i;
7821         float *vertex3f;
7822         float v[3];
7823         VectorSet(v, x, y, z);
7824         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7825                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7826                         break;
7827         if (i == mesh->numvertices)
7828         {
7829                 if (mesh->numvertices < mesh->maxvertices)
7830                 {
7831                         VectorCopy(v, vertex3f);
7832                         mesh->numvertices++;
7833                 }
7834                 return mesh->numvertices;
7835         }
7836         else
7837                 return i;
7838 }
7839
7840 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7841 {
7842         int i;
7843         int *e, element[3];
7844         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7845         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7846         e = mesh->element3i + mesh->numtriangles * 3;
7847         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7848         {
7849                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7850                 if (mesh->numtriangles < mesh->maxtriangles)
7851                 {
7852                         *e++ = element[0];
7853                         *e++ = element[1];
7854                         *e++ = element[2];
7855                         mesh->numtriangles++;
7856                 }
7857                 element[1] = element[2];
7858         }
7859 }
7860
7861 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7862 {
7863         int i;
7864         int *e, element[3];
7865         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7866         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7867         e = mesh->element3i + mesh->numtriangles * 3;
7868         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7869         {
7870                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7871                 if (mesh->numtriangles < mesh->maxtriangles)
7872                 {
7873                         *e++ = element[0];
7874                         *e++ = element[1];
7875                         *e++ = element[2];
7876                         mesh->numtriangles++;
7877                 }
7878                 element[1] = element[2];
7879         }
7880 }
7881
7882 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7883 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7884 {
7885         int planenum, planenum2;
7886         int w;
7887         int tempnumpoints;
7888         mplane_t *plane, *plane2;
7889         double maxdist;
7890         double temppoints[2][256*3];
7891         // figure out how large a bounding box we need to properly compute this brush
7892         maxdist = 0;
7893         for (w = 0;w < numplanes;w++)
7894                 maxdist = max(maxdist, fabs(planes[w].dist));
7895         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7896         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7897         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7898         {
7899                 w = 0;
7900                 tempnumpoints = 4;
7901                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7902                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7903                 {
7904                         if (planenum2 == planenum)
7905                                 continue;
7906                         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);
7907                         w = !w;
7908                 }
7909                 if (tempnumpoints < 3)
7910                         continue;
7911                 // generate elements forming a triangle fan for this polygon
7912                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7913         }
7914 }
7915
7916 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)
7917 {
7918         texturelayer_t *layer;
7919         layer = t->currentlayers + t->currentnumlayers++;
7920         layer->type = type;
7921         layer->depthmask = depthmask;
7922         layer->blendfunc1 = blendfunc1;
7923         layer->blendfunc2 = blendfunc2;
7924         layer->texture = texture;
7925         layer->texmatrix = *matrix;
7926         layer->color[0] = r;
7927         layer->color[1] = g;
7928         layer->color[2] = b;
7929         layer->color[3] = a;
7930 }
7931
7932 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7933 {
7934         if(parms[0] == 0 && parms[1] == 0)
7935                 return false;
7936         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7937                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7938                         return false;
7939         return true;
7940 }
7941
7942 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7943 {
7944         double index, f;
7945         index = parms[2] + rsurface.shadertime * parms[3];
7946         index -= floor(index);
7947         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7948         {
7949         default:
7950         case Q3WAVEFUNC_NONE:
7951         case Q3WAVEFUNC_NOISE:
7952         case Q3WAVEFUNC_COUNT:
7953                 f = 0;
7954                 break;
7955         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7956         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7957         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7958         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7959         case Q3WAVEFUNC_TRIANGLE:
7960                 index *= 4;
7961                 f = index - floor(index);
7962                 if (index < 1)
7963                 {
7964                         // f = f;
7965                 }
7966                 else if (index < 2)
7967                         f = 1 - f;
7968                 else if (index < 3)
7969                         f = -f;
7970                 else
7971                         f = -(1 - f);
7972                 break;
7973         }
7974         f = parms[0] + parms[1] * f;
7975         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7976                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7977         return (float) f;
7978 }
7979
7980 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7981 {
7982         int w, h, idx;
7983         float shadertime;
7984         float f;
7985         float offsetd[2];
7986         float tcmat[12];
7987         matrix4x4_t matrix, temp;
7988         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7989         // it's better to have one huge fixup every 9 hours than gradual
7990         // degradation over time which looks consistently bad after many hours.
7991         //
7992         // tcmod scroll in particular suffers from this degradation which can't be
7993         // effectively worked around even with floor() tricks because we don't
7994         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7995         // a workaround involving floor() would be incorrect anyway...
7996         shadertime = rsurface.shadertime;
7997         if (shadertime >= 32768.0f)
7998                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7999         switch(tcmod->tcmod)
8000         {
8001                 case Q3TCMOD_COUNT:
8002                 case Q3TCMOD_NONE:
8003                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8004                                 matrix = r_waterscrollmatrix;
8005                         else
8006                                 matrix = identitymatrix;
8007                         break;
8008                 case Q3TCMOD_ENTITYTRANSLATE:
8009                         // this is used in Q3 to allow the gamecode to control texcoord
8010                         // scrolling on the entity, which is not supported in darkplaces yet.
8011                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8012                         break;
8013                 case Q3TCMOD_ROTATE:
8014                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8015                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8016                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8017                         break;
8018                 case Q3TCMOD_SCALE:
8019                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8020                         break;
8021                 case Q3TCMOD_SCROLL:
8022                         // this particular tcmod is a "bug for bug" compatible one with regards to
8023                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8024                         // specifically did the wrapping and so we must mimic that...
8025                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8026                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8027                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8028                         break;
8029                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8030                         w = (int) tcmod->parms[0];
8031                         h = (int) tcmod->parms[1];
8032                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8033                         f = f - floor(f);
8034                         idx = (int) floor(f * w * h);
8035                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8036                         break;
8037                 case Q3TCMOD_STRETCH:
8038                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8039                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8040                         break;
8041                 case Q3TCMOD_TRANSFORM:
8042                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8043                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8044                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8045                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8046                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8047                         break;
8048                 case Q3TCMOD_TURBULENT:
8049                         // this is handled in the RSurf_PrepareVertices function
8050                         matrix = identitymatrix;
8051                         break;
8052         }
8053         temp = *texmatrix;
8054         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8055 }
8056
8057 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8058 {
8059         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8060         char name[MAX_QPATH];
8061         skinframe_t *skinframe;
8062         unsigned char pixels[296*194];
8063         strlcpy(cache->name, skinname, sizeof(cache->name));
8064         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8065         if (developer_loading.integer)
8066                 Con_Printf("loading %s\n", name);
8067         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8068         if (!skinframe || !skinframe->base)
8069         {
8070                 unsigned char *f;
8071                 fs_offset_t filesize;
8072                 skinframe = NULL;
8073                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8074                 if (f)
8075                 {
8076                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8077                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8078                         Mem_Free(f);
8079                 }
8080         }
8081         cache->skinframe = skinframe;
8082 }
8083
8084 texture_t *R_GetCurrentTexture(texture_t *t)
8085 {
8086         int i, q;
8087         const entity_render_t *ent = rsurface.entity;
8088         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8089         q3shaderinfo_layer_tcmod_t *tcmod;
8090         float specularscale = 0.0f;
8091
8092         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8093                 return t->currentframe;
8094         t->update_lastrenderframe = r_textureframe;
8095         t->update_lastrenderentity = (void *)ent;
8096
8097         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8098                 t->camera_entity = ent->entitynumber;
8099         else
8100                 t->camera_entity = 0;
8101
8102         // switch to an alternate material if this is a q1bsp animated material
8103         {
8104                 texture_t *texture = t;
8105                 int s = rsurface.ent_skinnum;
8106                 if ((unsigned int)s >= (unsigned int)model->numskins)
8107                         s = 0;
8108                 if (model->skinscenes)
8109                 {
8110                         if (model->skinscenes[s].framecount > 1)
8111                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8112                         else
8113                                 s = model->skinscenes[s].firstframe;
8114                 }
8115                 if (s > 0)
8116                         t = t + s * model->num_surfaces;
8117                 if (t->animated)
8118                 {
8119                         // use an alternate animation if the entity's frame is not 0,
8120                         // and only if the texture has an alternate animation
8121                         if (t->animated == 2) // q2bsp
8122                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8123                         else if (rsurface.ent_alttextures && t->anim_total[1])
8124                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8125                         else
8126                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8127                 }
8128                 texture->currentframe = t;
8129         }
8130
8131         // update currentskinframe to be a qw skin or animation frame
8132         if (rsurface.ent_qwskin >= 0)
8133         {
8134                 i = rsurface.ent_qwskin;
8135                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8136                 {
8137                         r_qwskincache_size = cl.maxclients;
8138                         if (r_qwskincache)
8139                                 Mem_Free(r_qwskincache);
8140                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8141                 }
8142                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8143                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8144                 t->currentskinframe = r_qwskincache[i].skinframe;
8145                 if (t->materialshaderpass && t->currentskinframe == NULL)
8146                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8147         }
8148         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8149                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8150         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8151                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8152
8153         t->currentmaterialflags = t->basematerialflags;
8154         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8155         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8156                 t->currentalpha *= r_wateralpha.value;
8157         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8158                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8159         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8160                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8161
8162         // decide on which type of lighting to use for this surface
8163         if (rsurface.entity->render_modellight_forced)
8164                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8165         if (rsurface.entity->render_rtlight_disabled)
8166                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8167         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8168         {
8169                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
8170                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8171                 for (q = 0; q < 3; q++)
8172                 {
8173                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8174                         t->render_modellight_lightdir[q] = q == 2;
8175                         t->render_modellight_ambient[q] = 1;
8176                         t->render_modellight_diffuse[q] = 0;
8177                         t->render_modellight_specular[q] = 0;
8178                         t->render_lightmap_ambient[q] = 0;
8179                         t->render_lightmap_diffuse[q] = 0;
8180                         t->render_lightmap_specular[q] = 0;
8181                         t->render_rtlight_diffuse[q] = 0;
8182                         t->render_rtlight_specular[q] = 0;
8183                 }
8184         }
8185         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8186         {
8187                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8188                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8189                 for (q = 0; q < 3; q++)
8190                 {
8191                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8192                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8193                         t->render_modellight_lightdir[q] = q == 2;
8194                         t->render_modellight_diffuse[q] = 0;
8195                         t->render_modellight_specular[q] = 0;
8196                         t->render_lightmap_ambient[q] = 0;
8197                         t->render_lightmap_diffuse[q] = 0;
8198                         t->render_lightmap_specular[q] = 0;
8199                         t->render_rtlight_diffuse[q] = 0;
8200                         t->render_rtlight_specular[q] = 0;
8201                 }
8202         }
8203         else if (FAKELIGHT_ENABLED)
8204         {
8205                 // no modellight if using fakelight for the map
8206                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8207                 for (q = 0; q < 3; q++)
8208                 {
8209                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8210                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8211                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8212                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8213                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8214                         t->render_lightmap_ambient[q] = 0;
8215                         t->render_lightmap_diffuse[q] = 0;
8216                         t->render_lightmap_specular[q] = 0;
8217                         t->render_rtlight_diffuse[q] = 0;
8218                         t->render_rtlight_specular[q] = 0;
8219                 }
8220         }
8221         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8222         {
8223                 // ambient + single direction light (modellight)
8224                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8225                 for (q = 0; q < 3; q++)
8226                 {
8227                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8228                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8229                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8230                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8231                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8232                         t->render_lightmap_ambient[q] = 0;
8233                         t->render_lightmap_diffuse[q] = 0;
8234                         t->render_lightmap_specular[q] = 0;
8235                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8236                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8237                 }
8238         }
8239         else
8240         {
8241                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8242                 for (q = 0; q < 3; q++)
8243                 {
8244                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8245                         t->render_modellight_lightdir[q] = q == 2;
8246                         t->render_modellight_ambient[q] = 0;
8247                         t->render_modellight_diffuse[q] = 0;
8248                         t->render_modellight_specular[q] = 0;
8249                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8250                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8251                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8252                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8253                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8254                 }
8255         }
8256
8257         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8258         {
8259                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8260                 // attribute, we punt it to the lightmap path and hope for the best,
8261                 // but lighting doesn't work.
8262                 //
8263                 // FIXME: this is fine for effects but CSQC polygons should be subject
8264                 // to lighting.
8265                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8266                 for (q = 0; q < 3; q++)
8267                 {
8268                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8269                         t->render_modellight_lightdir[q] = q == 2;
8270                         t->render_modellight_ambient[q] = 0;
8271                         t->render_modellight_diffuse[q] = 0;
8272                         t->render_modellight_specular[q] = 0;
8273                         t->render_lightmap_ambient[q] = 0;
8274                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8275                         t->render_lightmap_specular[q] = 0;
8276                         t->render_rtlight_diffuse[q] = 0;
8277                         t->render_rtlight_specular[q] = 0;
8278                 }
8279         }
8280
8281         for (q = 0; q < 3; q++)
8282         {
8283                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8284                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8285         }
8286
8287         if (rsurface.ent_flags & RENDER_ADDITIVE)
8288                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8289         else if (t->currentalpha < 1)
8290                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8291         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8292         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8293                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8294         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8295                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8296         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8297                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8298         if (t->backgroundshaderpass)
8299                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8300         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8301         {
8302                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8303                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8304         }
8305         else
8306                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8307         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8308         {
8309                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8310                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8311         }
8312         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8313                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8314
8315         // there is no tcmod
8316         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8317         {
8318                 t->currenttexmatrix = r_waterscrollmatrix;
8319                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8320         }
8321         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8322         {
8323                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8324                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8325         }
8326
8327         if (t->materialshaderpass)
8328                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8329                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8330
8331         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8332         if (t->currentskinframe->qpixels)
8333                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8334         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8335         if (!t->basetexture)
8336                 t->basetexture = r_texture_notexture;
8337         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8338         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8339         t->nmaptexture = t->currentskinframe->nmap;
8340         if (!t->nmaptexture)
8341                 t->nmaptexture = r_texture_blanknormalmap;
8342         t->glosstexture = r_texture_black;
8343         t->glowtexture = t->currentskinframe->glow;
8344         t->fogtexture = t->currentskinframe->fog;
8345         t->reflectmasktexture = t->currentskinframe->reflect;
8346         if (t->backgroundshaderpass)
8347         {
8348                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8349                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8350                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8351                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8352                 t->backgroundglosstexture = r_texture_black;
8353                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8354                 if (!t->backgroundnmaptexture)
8355                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8356                 // make sure that if glow is going to be used, both textures are not NULL
8357                 if (!t->backgroundglowtexture && t->glowtexture)
8358                         t->backgroundglowtexture = r_texture_black;
8359                 if (!t->glowtexture && t->backgroundglowtexture)
8360                         t->glowtexture = r_texture_black;
8361         }
8362         else
8363         {
8364                 t->backgroundbasetexture = r_texture_white;
8365                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8366                 t->backgroundglosstexture = r_texture_black;
8367                 t->backgroundglowtexture = NULL;
8368         }
8369         t->specularpower = r_shadow_glossexponent.value;
8370         // TODO: store reference values for these in the texture?
8371         if (r_shadow_gloss.integer > 0)
8372         {
8373                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8374                 {
8375                         if (r_shadow_glossintensity.value > 0)
8376                         {
8377                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8378                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8379                                 specularscale = r_shadow_glossintensity.value;
8380                         }
8381                 }
8382                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8383                 {
8384                         t->glosstexture = r_texture_white;
8385                         t->backgroundglosstexture = r_texture_white;
8386                         specularscale = r_shadow_gloss2intensity.value;
8387                         t->specularpower = r_shadow_gloss2exponent.value;
8388                 }
8389         }
8390         specularscale *= t->specularscalemod;
8391         t->specularpower *= t->specularpowermod;
8392
8393         // lightmaps mode looks bad with dlights using actual texturing, so turn
8394         // off the colormap and glossmap, but leave the normalmap on as it still
8395         // accurately represents the shading involved
8396         if (gl_lightmaps.integer)
8397         {
8398                 t->basetexture = r_texture_grey128;
8399                 t->pantstexture = r_texture_black;
8400                 t->shirttexture = r_texture_black;
8401                 if (gl_lightmaps.integer < 2)
8402                         t->nmaptexture = r_texture_blanknormalmap;
8403                 t->glosstexture = r_texture_black;
8404                 t->glowtexture = NULL;
8405                 t->fogtexture = NULL;
8406                 t->reflectmasktexture = NULL;
8407                 t->backgroundbasetexture = NULL;
8408                 if (gl_lightmaps.integer < 2)
8409                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8410                 t->backgroundglosstexture = r_texture_black;
8411                 t->backgroundglowtexture = NULL;
8412                 specularscale = 0;
8413                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8414         }
8415
8416         if (specularscale != 1.0f)
8417         {
8418                 for (q = 0; q < 3; q++)
8419                 {
8420                         t->render_modellight_specular[q] *= specularscale;
8421                         t->render_lightmap_specular[q] *= specularscale;
8422                         t->render_rtlight_specular[q] *= specularscale;
8423                 }
8424         }
8425
8426         t->currentnumlayers = 0;
8427         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8428         {
8429                 int blendfunc1, blendfunc2;
8430                 qboolean depthmask;
8431                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8432                 {
8433                         blendfunc1 = GL_SRC_ALPHA;
8434                         blendfunc2 = GL_ONE;
8435                 }
8436                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8437                 {
8438                         blendfunc1 = GL_SRC_ALPHA;
8439                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8440                 }
8441                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8442                 {
8443                         blendfunc1 = t->customblendfunc[0];
8444                         blendfunc2 = t->customblendfunc[1];
8445                 }
8446                 else
8447                 {
8448                         blendfunc1 = GL_ONE;
8449                         blendfunc2 = GL_ZERO;
8450                 }
8451                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8452                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8453                 {
8454                         // basic lit geometry
8455                         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);
8456                         // add pants/shirt if needed
8457                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8458                                 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);
8459                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8460                                 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);
8461                 }
8462                 else
8463                 {
8464                         // basic lit geometry
8465                         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);
8466                         // add pants/shirt if needed
8467                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8468                                 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);
8469                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8470                                 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);
8471                         // now add ambient passes if needed
8472                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8473                         {
8474                                 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);
8475                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8476                                         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);
8477                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8478                                         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);
8479                         }
8480                 }
8481                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8482                         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);
8483                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8484                 {
8485                         // if this is opaque use alpha blend which will darken the earlier
8486                         // passes cheaply.
8487                         //
8488                         // if this is an alpha blended material, all the earlier passes
8489                         // were darkened by fog already, so we only need to add the fog
8490                         // color ontop through the fog mask texture
8491                         //
8492                         // if this is an additive blended material, all the earlier passes
8493                         // were darkened by fog already, and we should not add fog color
8494                         // (because the background was not darkened, there is no fog color
8495                         // that was lost behind it).
8496                         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);
8497                 }
8498         }
8499
8500         return t;
8501 }
8502
8503 rsurfacestate_t rsurface;
8504
8505 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8506 {
8507         dp_model_t *model = ent->model;
8508         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8509         //      return;
8510         rsurface.entity = (entity_render_t *)ent;
8511         rsurface.skeleton = ent->skeleton;
8512         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8513         rsurface.ent_skinnum = ent->skinnum;
8514         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;
8515         rsurface.ent_flags = ent->flags;
8516         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8517                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8518         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8519         rsurface.matrix = ent->matrix;
8520         rsurface.inversematrix = ent->inversematrix;
8521         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8522         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8523         R_EntityMatrix(&rsurface.matrix);
8524         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8525         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8526         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8527         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8528         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8529         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8530         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8531         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8532         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8533         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8534         if (ent->model->brush.submodel && !prepass)
8535         {
8536                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8537                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8538         }
8539         // if the animcache code decided it should use the shader path, skip the deform step
8540         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8541         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8542         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8543         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8544         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8545         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8546         {
8547                 if (ent->animcache_vertex3f)
8548                 {
8549                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8550                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8551                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8552                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8553                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8554                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8555                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8556                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8557                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8558                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8559                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8560                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8561                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8562                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8563                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8564                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8565                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8566                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8567                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8568                 }
8569                 else if (wanttangents)
8570                 {
8571                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8572                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8573                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8574                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8575                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8576                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8577                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8578                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8579                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8580                         rsurface.modelvertexmesh = NULL;
8581                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8582                         rsurface.modelvertexmesh_bufferoffset = 0;
8583                         rsurface.modelvertex3f_vertexbuffer = NULL;
8584                         rsurface.modelvertex3f_bufferoffset = 0;
8585                         rsurface.modelvertex3f_vertexbuffer = 0;
8586                         rsurface.modelvertex3f_bufferoffset = 0;
8587                         rsurface.modelsvector3f_vertexbuffer = 0;
8588                         rsurface.modelsvector3f_bufferoffset = 0;
8589                         rsurface.modeltvector3f_vertexbuffer = 0;
8590                         rsurface.modeltvector3f_bufferoffset = 0;
8591                         rsurface.modelnormal3f_vertexbuffer = 0;
8592                         rsurface.modelnormal3f_bufferoffset = 0;
8593                 }
8594                 else if (wantnormals)
8595                 {
8596                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8597                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8598                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8599                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8600                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8601                         rsurface.modelsvector3f = NULL;
8602                         rsurface.modeltvector3f = NULL;
8603                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8604                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8605                         rsurface.modelvertexmesh = NULL;
8606                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8607                         rsurface.modelvertexmesh_bufferoffset = 0;
8608                         rsurface.modelvertex3f_vertexbuffer = NULL;
8609                         rsurface.modelvertex3f_bufferoffset = 0;
8610                         rsurface.modelvertex3f_vertexbuffer = 0;
8611                         rsurface.modelvertex3f_bufferoffset = 0;
8612                         rsurface.modelsvector3f_vertexbuffer = 0;
8613                         rsurface.modelsvector3f_bufferoffset = 0;
8614                         rsurface.modeltvector3f_vertexbuffer = 0;
8615                         rsurface.modeltvector3f_bufferoffset = 0;
8616                         rsurface.modelnormal3f_vertexbuffer = 0;
8617                         rsurface.modelnormal3f_bufferoffset = 0;
8618                 }
8619                 else
8620                 {
8621                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8622                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8623                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8624                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8625                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626                         rsurface.modelsvector3f = NULL;
8627                         rsurface.modeltvector3f = NULL;
8628                         rsurface.modelnormal3f = NULL;
8629                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8630                         rsurface.modelvertexmesh = NULL;
8631                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8632                         rsurface.modelvertexmesh_bufferoffset = 0;
8633                         rsurface.modelvertex3f_vertexbuffer = NULL;
8634                         rsurface.modelvertex3f_bufferoffset = 0;
8635                         rsurface.modelvertex3f_vertexbuffer = 0;
8636                         rsurface.modelvertex3f_bufferoffset = 0;
8637                         rsurface.modelsvector3f_vertexbuffer = 0;
8638                         rsurface.modelsvector3f_bufferoffset = 0;
8639                         rsurface.modeltvector3f_vertexbuffer = 0;
8640                         rsurface.modeltvector3f_bufferoffset = 0;
8641                         rsurface.modelnormal3f_vertexbuffer = 0;
8642                         rsurface.modelnormal3f_bufferoffset = 0;
8643                 }
8644                 rsurface.modelgeneratedvertex = true;
8645         }
8646         else
8647         {
8648                 if (rsurface.entityskeletaltransform3x4)
8649                 {
8650                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8651                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8652                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8653                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8654                 }
8655                 else
8656                 {
8657                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8658                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8659                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8660                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8661                 }
8662                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8663                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8664                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8665                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8666                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8667                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8668                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8669                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8670                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8671                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8672                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8673                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8674                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8675                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8676                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8677                 rsurface.modelgeneratedvertex = false;
8678         }
8679         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8680         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8681         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8682         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8683         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8684         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8685         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8686         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8687         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8688         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8689         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8690         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8691         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8692         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8693         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8694         rsurface.modelelement3i = model->surfmesh.data_element3i;
8695         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8696         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8697         rsurface.modelelement3s = model->surfmesh.data_element3s;
8698         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8699         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8700         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8701         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8702         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8703         rsurface.modelsurfaces = model->data_surfaces;
8704         rsurface.batchgeneratedvertex = false;
8705         rsurface.batchfirstvertex = 0;
8706         rsurface.batchnumvertices = 0;
8707         rsurface.batchfirsttriangle = 0;
8708         rsurface.batchnumtriangles = 0;
8709         rsurface.batchvertex3f  = NULL;
8710         rsurface.batchvertex3f_vertexbuffer = NULL;
8711         rsurface.batchvertex3f_bufferoffset = 0;
8712         rsurface.batchsvector3f = NULL;
8713         rsurface.batchsvector3f_vertexbuffer = NULL;
8714         rsurface.batchsvector3f_bufferoffset = 0;
8715         rsurface.batchtvector3f = NULL;
8716         rsurface.batchtvector3f_vertexbuffer = NULL;
8717         rsurface.batchtvector3f_bufferoffset = 0;
8718         rsurface.batchnormal3f  = NULL;
8719         rsurface.batchnormal3f_vertexbuffer = NULL;
8720         rsurface.batchnormal3f_bufferoffset = 0;
8721         rsurface.batchlightmapcolor4f = NULL;
8722         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8723         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8724         rsurface.batchtexcoordtexture2f = NULL;
8725         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8726         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8727         rsurface.batchtexcoordlightmap2f = NULL;
8728         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8729         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8730         rsurface.batchskeletalindex4ub = NULL;
8731         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8732         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8733         rsurface.batchskeletalweight4ub = NULL;
8734         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8735         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8736         rsurface.batchvertexmesh = NULL;
8737         rsurface.batchvertexmesh_vertexbuffer = NULL;
8738         rsurface.batchvertexmesh_bufferoffset = 0;
8739         rsurface.batchelement3i = NULL;
8740         rsurface.batchelement3i_indexbuffer = NULL;
8741         rsurface.batchelement3i_bufferoffset = 0;
8742         rsurface.batchelement3s = NULL;
8743         rsurface.batchelement3s_indexbuffer = NULL;
8744         rsurface.batchelement3s_bufferoffset = 0;
8745         rsurface.passcolor4f = NULL;
8746         rsurface.passcolor4f_vertexbuffer = NULL;
8747         rsurface.passcolor4f_bufferoffset = 0;
8748         rsurface.forcecurrenttextureupdate = false;
8749 }
8750
8751 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)
8752 {
8753         rsurface.entity = r_refdef.scene.worldentity;
8754         rsurface.skeleton = NULL;
8755         rsurface.ent_skinnum = 0;
8756         rsurface.ent_qwskin = -1;
8757         rsurface.ent_flags = entflags;
8758         rsurface.shadertime = r_refdef.scene.time - shadertime;
8759         rsurface.modelnumvertices = numvertices;
8760         rsurface.modelnumtriangles = numtriangles;
8761         rsurface.matrix = *matrix;
8762         rsurface.inversematrix = *inversematrix;
8763         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8764         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8765         R_EntityMatrix(&rsurface.matrix);
8766         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8767         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8768         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8769         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8770         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8771         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8772         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8773         rsurface.frameblend[0].lerp = 1;
8774         rsurface.ent_alttextures = false;
8775         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8776         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8777         rsurface.entityskeletaltransform3x4 = NULL;
8778         rsurface.entityskeletaltransform3x4buffer = NULL;
8779         rsurface.entityskeletaltransform3x4offset = 0;
8780         rsurface.entityskeletaltransform3x4size = 0;
8781         rsurface.entityskeletalnumtransforms = 0;
8782         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8783         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8784         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8785         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8786         if (wanttangents)
8787         {
8788                 rsurface.modelvertex3f = (float *)vertex3f;
8789                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8790                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8791                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8792         }
8793         else if (wantnormals)
8794         {
8795                 rsurface.modelvertex3f = (float *)vertex3f;
8796                 rsurface.modelsvector3f = NULL;
8797                 rsurface.modeltvector3f = NULL;
8798                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8799         }
8800         else
8801         {
8802                 rsurface.modelvertex3f = (float *)vertex3f;
8803                 rsurface.modelsvector3f = NULL;
8804                 rsurface.modeltvector3f = NULL;
8805                 rsurface.modelnormal3f = NULL;
8806         }
8807         rsurface.modelvertexmesh = NULL;
8808         rsurface.modelvertexmesh_vertexbuffer = NULL;
8809         rsurface.modelvertexmesh_bufferoffset = 0;
8810         rsurface.modelvertex3f_vertexbuffer = 0;
8811         rsurface.modelvertex3f_bufferoffset = 0;
8812         rsurface.modelsvector3f_vertexbuffer = 0;
8813         rsurface.modelsvector3f_bufferoffset = 0;
8814         rsurface.modeltvector3f_vertexbuffer = 0;
8815         rsurface.modeltvector3f_bufferoffset = 0;
8816         rsurface.modelnormal3f_vertexbuffer = 0;
8817         rsurface.modelnormal3f_bufferoffset = 0;
8818         rsurface.modelgeneratedvertex = true;
8819         rsurface.modellightmapcolor4f  = (float *)color4f;
8820         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8821         rsurface.modellightmapcolor4f_bufferoffset = 0;
8822         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8823         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8824         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8825         rsurface.modeltexcoordlightmap2f  = NULL;
8826         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8827         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8828         rsurface.modelskeletalindex4ub = NULL;
8829         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8830         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8831         rsurface.modelskeletalweight4ub = NULL;
8832         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8833         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8834         rsurface.modelelement3i = (int *)element3i;
8835         rsurface.modelelement3i_indexbuffer = NULL;
8836         rsurface.modelelement3i_bufferoffset = 0;
8837         rsurface.modelelement3s = (unsigned short *)element3s;
8838         rsurface.modelelement3s_indexbuffer = NULL;
8839         rsurface.modelelement3s_bufferoffset = 0;
8840         rsurface.modellightmapoffsets = NULL;
8841         rsurface.modelsurfaces = NULL;
8842         rsurface.batchgeneratedvertex = false;
8843         rsurface.batchfirstvertex = 0;
8844         rsurface.batchnumvertices = 0;
8845         rsurface.batchfirsttriangle = 0;
8846         rsurface.batchnumtriangles = 0;
8847         rsurface.batchvertex3f  = NULL;
8848         rsurface.batchvertex3f_vertexbuffer = NULL;
8849         rsurface.batchvertex3f_bufferoffset = 0;
8850         rsurface.batchsvector3f = NULL;
8851         rsurface.batchsvector3f_vertexbuffer = NULL;
8852         rsurface.batchsvector3f_bufferoffset = 0;
8853         rsurface.batchtvector3f = NULL;
8854         rsurface.batchtvector3f_vertexbuffer = NULL;
8855         rsurface.batchtvector3f_bufferoffset = 0;
8856         rsurface.batchnormal3f  = NULL;
8857         rsurface.batchnormal3f_vertexbuffer = NULL;
8858         rsurface.batchnormal3f_bufferoffset = 0;
8859         rsurface.batchlightmapcolor4f = NULL;
8860         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8861         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8862         rsurface.batchtexcoordtexture2f = NULL;
8863         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8864         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8865         rsurface.batchtexcoordlightmap2f = NULL;
8866         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8867         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8868         rsurface.batchskeletalindex4ub = NULL;
8869         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8870         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8871         rsurface.batchskeletalweight4ub = NULL;
8872         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8873         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8874         rsurface.batchvertexmesh = NULL;
8875         rsurface.batchvertexmesh_vertexbuffer = NULL;
8876         rsurface.batchvertexmesh_bufferoffset = 0;
8877         rsurface.batchelement3i = NULL;
8878         rsurface.batchelement3i_indexbuffer = NULL;
8879         rsurface.batchelement3i_bufferoffset = 0;
8880         rsurface.batchelement3s = NULL;
8881         rsurface.batchelement3s_indexbuffer = NULL;
8882         rsurface.batchelement3s_bufferoffset = 0;
8883         rsurface.passcolor4f = NULL;
8884         rsurface.passcolor4f_vertexbuffer = NULL;
8885         rsurface.passcolor4f_bufferoffset = 0;
8886         rsurface.forcecurrenttextureupdate = true;
8887
8888         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8889         {
8890                 if ((wantnormals || wanttangents) && !normal3f)
8891                 {
8892                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8893                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8894                 }
8895                 if (wanttangents && !svector3f)
8896                 {
8897                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8898                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8899                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8900                 }
8901         }
8902 }
8903
8904 float RSurf_FogPoint(const float *v)
8905 {
8906         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8907         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8908         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8909         float FogHeightFade = r_refdef.fogheightfade;
8910         float fogfrac;
8911         unsigned int fogmasktableindex;
8912         if (r_refdef.fogplaneviewabove)
8913                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8914         else
8915                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8916         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8917         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8918 }
8919
8920 float RSurf_FogVertex(const float *v)
8921 {
8922         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8923         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8924         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8925         float FogHeightFade = rsurface.fogheightfade;
8926         float fogfrac;
8927         unsigned int fogmasktableindex;
8928         if (r_refdef.fogplaneviewabove)
8929                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8930         else
8931                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8932         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8933         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8934 }
8935
8936 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8937 {
8938         int i;
8939         for (i = 0;i < numelements;i++)
8940                 outelement3i[i] = inelement3i[i] + adjust;
8941 }
8942
8943 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8944 extern cvar_t gl_vbo;
8945 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8946 {
8947         int deformindex;
8948         int firsttriangle;
8949         int numtriangles;
8950         int firstvertex;
8951         int endvertex;
8952         int numvertices;
8953         int surfacefirsttriangle;
8954         int surfacenumtriangles;
8955         int surfacefirstvertex;
8956         int surfaceendvertex;
8957         int surfacenumvertices;
8958         int batchnumsurfaces = texturenumsurfaces;
8959         int batchnumvertices;
8960         int batchnumtriangles;
8961         int needsupdate;
8962         int i, j;
8963         qboolean gaps;
8964         qboolean dynamicvertex;
8965         float amplitude;
8966         float animpos;
8967         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8968         float waveparms[4];
8969         unsigned char *ub;
8970         q3shaderinfo_deform_t *deform;
8971         const msurface_t *surface, *firstsurface;
8972         r_vertexmesh_t *vertexmesh;
8973         if (!texturenumsurfaces)
8974                 return;
8975         // find vertex range of this surface batch
8976         gaps = false;
8977         firstsurface = texturesurfacelist[0];
8978         firsttriangle = firstsurface->num_firsttriangle;
8979         batchnumvertices = 0;
8980         batchnumtriangles = 0;
8981         firstvertex = endvertex = firstsurface->num_firstvertex;
8982         for (i = 0;i < texturenumsurfaces;i++)
8983         {
8984                 surface = texturesurfacelist[i];
8985                 if (surface != firstsurface + i)
8986                         gaps = true;
8987                 surfacefirstvertex = surface->num_firstvertex;
8988                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8989                 surfacenumvertices = surface->num_vertices;
8990                 surfacenumtriangles = surface->num_triangles;
8991                 if (firstvertex > surfacefirstvertex)
8992                         firstvertex = surfacefirstvertex;
8993                 if (endvertex < surfaceendvertex)
8994                         endvertex = surfaceendvertex;
8995                 batchnumvertices += surfacenumvertices;
8996                 batchnumtriangles += surfacenumtriangles;
8997         }
8998
8999         r_refdef.stats[r_stat_batch_batches]++;
9000         if (gaps)
9001                 r_refdef.stats[r_stat_batch_withgaps]++;
9002         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9003         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9004         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9005
9006         // we now know the vertex range used, and if there are any gaps in it
9007         rsurface.batchfirstvertex = firstvertex;
9008         rsurface.batchnumvertices = endvertex - firstvertex;
9009         rsurface.batchfirsttriangle = firsttriangle;
9010         rsurface.batchnumtriangles = batchnumtriangles;
9011
9012         // this variable holds flags for which properties have been updated that
9013         // may require regenerating vertexmesh array...
9014         needsupdate = 0;
9015
9016         // check if any dynamic vertex processing must occur
9017         dynamicvertex = false;
9018
9019         // a cvar to force the dynamic vertex path to be taken, for debugging
9020         if (r_batch_debugdynamicvertexpath.integer)
9021         {
9022                 if (!dynamicvertex)
9023                 {
9024                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9025                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9026                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9027                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9028                 }
9029                 dynamicvertex = true;
9030         }
9031
9032         // if there is a chance of animated vertex colors, it's a dynamic batch
9033         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9034         {
9035                 if (!dynamicvertex)
9036                 {
9037                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9038                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9039                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9040                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9041                 }
9042                 dynamicvertex = true;
9043                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9044         }
9045
9046         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9047         {
9048                 switch (deform->deform)
9049                 {
9050                 default:
9051                 case Q3DEFORM_PROJECTIONSHADOW:
9052                 case Q3DEFORM_TEXT0:
9053                 case Q3DEFORM_TEXT1:
9054                 case Q3DEFORM_TEXT2:
9055                 case Q3DEFORM_TEXT3:
9056                 case Q3DEFORM_TEXT4:
9057                 case Q3DEFORM_TEXT5:
9058                 case Q3DEFORM_TEXT6:
9059                 case Q3DEFORM_TEXT7:
9060                 case Q3DEFORM_NONE:
9061                         break;
9062                 case Q3DEFORM_AUTOSPRITE:
9063                         if (!dynamicvertex)
9064                         {
9065                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9066                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9067                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9068                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9069                         }
9070                         dynamicvertex = true;
9071                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9072                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9073                         break;
9074                 case Q3DEFORM_AUTOSPRITE2:
9075                         if (!dynamicvertex)
9076                         {
9077                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9078                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9079                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9080                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9081                         }
9082                         dynamicvertex = true;
9083                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9084                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9085                         break;
9086                 case Q3DEFORM_NORMAL:
9087                         if (!dynamicvertex)
9088                         {
9089                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9090                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9091                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9092                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9093                         }
9094                         dynamicvertex = true;
9095                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9096                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9097                         break;
9098                 case Q3DEFORM_WAVE:
9099                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9100                                 break; // if wavefunc is a nop, ignore this transform
9101                         if (!dynamicvertex)
9102                         {
9103                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9104                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9105                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9106                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9107                         }
9108                         dynamicvertex = true;
9109                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9110                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9111                         break;
9112                 case Q3DEFORM_BULGE:
9113                         if (!dynamicvertex)
9114                         {
9115                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9116                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9117                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9118                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9119                         }
9120                         dynamicvertex = true;
9121                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9122                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9123                         break;
9124                 case Q3DEFORM_MOVE:
9125                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9126                                 break; // if wavefunc is a nop, ignore this transform
9127                         if (!dynamicvertex)
9128                         {
9129                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9130                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9131                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9132                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9133                         }
9134                         dynamicvertex = true;
9135                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9136                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9137                         break;
9138                 }
9139         }
9140         if (rsurface.texture->materialshaderpass)
9141         {
9142                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9143                 {
9144                 default:
9145                 case Q3TCGEN_TEXTURE:
9146                         break;
9147                 case Q3TCGEN_LIGHTMAP:
9148                         if (!dynamicvertex)
9149                         {
9150                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9151                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9152                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9153                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9154                         }
9155                         dynamicvertex = true;
9156                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9157                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9158                         break;
9159                 case Q3TCGEN_VECTOR:
9160                         if (!dynamicvertex)
9161                         {
9162                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9163                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9164                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9165                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9166                         }
9167                         dynamicvertex = true;
9168                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9169                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9170                         break;
9171                 case Q3TCGEN_ENVIRONMENT:
9172                         if (!dynamicvertex)
9173                         {
9174                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9175                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9176                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9177                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9178                         }
9179                         dynamicvertex = true;
9180                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9181                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9182                         break;
9183                 }
9184                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9185                 {
9186                         if (!dynamicvertex)
9187                         {
9188                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9189                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9190                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9191                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9192                         }
9193                         dynamicvertex = true;
9194                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9195                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9196                 }
9197         }
9198
9199         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9200         {
9201                 if (!dynamicvertex)
9202                 {
9203                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9204                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9205                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9206                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9207                 }
9208                 dynamicvertex = true;
9209                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9210         }
9211
9212         // when the model data has no vertex buffer (dynamic mesh), we need to
9213         // eliminate gaps
9214         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9215                 batchneed |= BATCHNEED_NOGAPS;
9216
9217         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9218         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9219         // we ensure this by treating the vertex batch as dynamic...
9220         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9221         {
9222                 if (!dynamicvertex)
9223                 {
9224                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9225                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9226                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9227                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9228                 }
9229                 dynamicvertex = true;
9230         }
9231
9232         if (dynamicvertex)
9233         {
9234                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9235                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9236                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9237                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9238                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9239                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9240                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9241                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9242         }
9243
9244         // if needsupdate, we have to do a dynamic vertex batch for sure
9245         if (needsupdate & batchneed)
9246         {
9247                 if (!dynamicvertex)
9248                 {
9249                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9250                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9251                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9252                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9253                 }
9254                 dynamicvertex = true;
9255         }
9256
9257         // see if we need to build vertexmesh from arrays
9258         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9259         {
9260                 if (!dynamicvertex)
9261                 {
9262                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9263                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9264                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9265                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9266                 }
9267                 dynamicvertex = true;
9268         }
9269
9270         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9271         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9272                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9273
9274         rsurface.batchvertex3f = rsurface.modelvertex3f;
9275         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9276         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9277         rsurface.batchsvector3f = rsurface.modelsvector3f;
9278         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9279         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9280         rsurface.batchtvector3f = rsurface.modeltvector3f;
9281         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9282         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9283         rsurface.batchnormal3f = rsurface.modelnormal3f;
9284         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9285         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9286         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9287         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9288         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9289         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9290         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9291         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9292         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9293         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9294         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9295         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9296         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9297         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9298         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9299         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9300         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9301         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9302         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9303         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9304         rsurface.batchelement3i = rsurface.modelelement3i;
9305         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9306         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9307         rsurface.batchelement3s = rsurface.modelelement3s;
9308         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9309         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9310         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9311         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9312         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9313         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9314         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9315
9316         // if any dynamic vertex processing has to occur in software, we copy the
9317         // entire surface list together before processing to rebase the vertices
9318         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9319         //
9320         // if any gaps exist and we do not have a static vertex buffer, we have to
9321         // copy the surface list together to avoid wasting upload bandwidth on the
9322         // vertices in the gaps.
9323         //
9324         // if gaps exist and we have a static vertex buffer, we can choose whether
9325         // to combine the index buffer ranges into one dynamic index buffer or
9326         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9327         //
9328         // in many cases the batch is reduced to one draw call.
9329
9330         rsurface.batchmultidraw = false;
9331         rsurface.batchmultidrawnumsurfaces = 0;
9332         rsurface.batchmultidrawsurfacelist = NULL;
9333
9334         if (!dynamicvertex)
9335         {
9336                 // static vertex data, just set pointers...
9337                 rsurface.batchgeneratedvertex = false;
9338                 // if there are gaps, we want to build a combined index buffer,
9339                 // otherwise use the original static buffer with an appropriate offset
9340                 if (gaps)
9341                 {
9342                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9343                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9344                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9345                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9346                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9347                         {
9348                                 rsurface.batchmultidraw = true;
9349                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9350                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9351                                 return;
9352                         }
9353                         // build a new triangle elements array for this batch
9354                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9355                         rsurface.batchfirsttriangle = 0;
9356                         numtriangles = 0;
9357                         for (i = 0;i < texturenumsurfaces;i++)
9358                         {
9359                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9360                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9361                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9362                                 numtriangles += surfacenumtriangles;
9363                         }
9364                         rsurface.batchelement3i_indexbuffer = NULL;
9365                         rsurface.batchelement3i_bufferoffset = 0;
9366                         rsurface.batchelement3s = NULL;
9367                         rsurface.batchelement3s_indexbuffer = NULL;
9368                         rsurface.batchelement3s_bufferoffset = 0;
9369                         if (endvertex <= 65536)
9370                         {
9371                                 // make a 16bit (unsigned short) index array if possible
9372                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9373                                 for (i = 0;i < numtriangles*3;i++)
9374                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9375                         }
9376                         // upload buffer data for the copytriangles batch
9377                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9378                         {
9379                                 if (rsurface.batchelement3s)
9380                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9381                                 else if (rsurface.batchelement3i)
9382                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9383                         }
9384                 }
9385                 else
9386                 {
9387                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9388                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9389                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9390                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9391                 }
9392                 return;
9393         }
9394
9395         // something needs software processing, do it for real...
9396         // we only directly handle separate array data in this case and then
9397         // generate interleaved data if needed...
9398         rsurface.batchgeneratedvertex = true;
9399         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9400         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9401         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9402         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9403
9404         // now copy the vertex data into a combined array and make an index array
9405         // (this is what Quake3 does all the time)
9406         // we also apply any skeletal animation here that would have been done in
9407         // the vertex shader, because most of the dynamic vertex animation cases
9408         // need actual vertex positions and normals
9409         //if (dynamicvertex)
9410         {
9411                 rsurface.batchvertexmesh = NULL;
9412                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9413                 rsurface.batchvertexmesh_bufferoffset = 0;
9414                 rsurface.batchvertex3f = NULL;
9415                 rsurface.batchvertex3f_vertexbuffer = NULL;
9416                 rsurface.batchvertex3f_bufferoffset = 0;
9417                 rsurface.batchsvector3f = NULL;
9418                 rsurface.batchsvector3f_vertexbuffer = NULL;
9419                 rsurface.batchsvector3f_bufferoffset = 0;
9420                 rsurface.batchtvector3f = NULL;
9421                 rsurface.batchtvector3f_vertexbuffer = NULL;
9422                 rsurface.batchtvector3f_bufferoffset = 0;
9423                 rsurface.batchnormal3f = NULL;
9424                 rsurface.batchnormal3f_vertexbuffer = NULL;
9425                 rsurface.batchnormal3f_bufferoffset = 0;
9426                 rsurface.batchlightmapcolor4f = NULL;
9427                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9428                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9429                 rsurface.batchtexcoordtexture2f = NULL;
9430                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9431                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9432                 rsurface.batchtexcoordlightmap2f = NULL;
9433                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9434                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9435                 rsurface.batchskeletalindex4ub = NULL;
9436                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9437                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9438                 rsurface.batchskeletalweight4ub = NULL;
9439                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9440                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9441                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9442                 rsurface.batchelement3i_indexbuffer = NULL;
9443                 rsurface.batchelement3i_bufferoffset = 0;
9444                 rsurface.batchelement3s = NULL;
9445                 rsurface.batchelement3s_indexbuffer = NULL;
9446                 rsurface.batchelement3s_bufferoffset = 0;
9447                 rsurface.batchskeletaltransform3x4buffer = NULL;
9448                 rsurface.batchskeletaltransform3x4offset = 0;
9449                 rsurface.batchskeletaltransform3x4size = 0;
9450                 // we'll only be setting up certain arrays as needed
9451                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9452                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9453                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9454                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9455                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9456                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9457                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9458                 {
9459                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9460                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9461                 }
9462                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9463                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9464                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9465                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9466                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9467                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9468                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9469                 {
9470                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9471                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9472                 }
9473                 numvertices = 0;
9474                 numtriangles = 0;
9475                 for (i = 0;i < texturenumsurfaces;i++)
9476                 {
9477                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9478                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9479                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9480                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9481                         // copy only the data requested
9482                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9483                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9484                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9485                         {
9486                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9487                                 {
9488                                         if (rsurface.batchvertex3f)
9489                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9490                                         else
9491                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9492                                 }
9493                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9494                                 {
9495                                         if (rsurface.modelnormal3f)
9496                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9497                                         else
9498                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9499                                 }
9500                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9501                                 {
9502                                         if (rsurface.modelsvector3f)
9503                                         {
9504                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9505                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9506                                         }
9507                                         else
9508                                         {
9509                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9510                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9511                                         }
9512                                 }
9513                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9514                                 {
9515                                         if (rsurface.modellightmapcolor4f)
9516                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9517                                         else
9518                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9519                                 }
9520                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9521                                 {
9522                                         if (rsurface.modeltexcoordtexture2f)
9523                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9524                                         else
9525                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9526                                 }
9527                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9528                                 {
9529                                         if (rsurface.modeltexcoordlightmap2f)
9530                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9531                                         else
9532                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9533                                 }
9534                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9535                                 {
9536                                         if (rsurface.modelskeletalindex4ub)
9537                                         {
9538                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9539                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9540                                         }
9541                                         else
9542                                         {
9543                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9544                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9545                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9546                                                 for (j = 0;j < surfacenumvertices;j++)
9547                                                         ub[j*4] = 255;
9548                                         }
9549                                 }
9550                         }
9551                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9552                         numvertices += surfacenumvertices;
9553                         numtriangles += surfacenumtriangles;
9554                 }
9555
9556                 // generate a 16bit index array as well if possible
9557                 // (in general, dynamic batches fit)
9558                 if (numvertices <= 65536)
9559                 {
9560                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9561                         for (i = 0;i < numtriangles*3;i++)
9562                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9563                 }
9564
9565                 // since we've copied everything, the batch now starts at 0
9566                 rsurface.batchfirstvertex = 0;
9567                 rsurface.batchnumvertices = batchnumvertices;
9568                 rsurface.batchfirsttriangle = 0;
9569                 rsurface.batchnumtriangles = batchnumtriangles;
9570         }
9571
9572         // apply skeletal animation that would have been done in the vertex shader
9573         if (rsurface.batchskeletaltransform3x4)
9574         {
9575                 const unsigned char *si;
9576                 const unsigned char *sw;
9577                 const float *t[4];
9578                 const float *b = rsurface.batchskeletaltransform3x4;
9579                 float *vp, *vs, *vt, *vn;
9580                 float w[4];
9581                 float m[3][4], n[3][4];
9582                 float tp[3], ts[3], tt[3], tn[3];
9583                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9584                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9585                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9586                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9587                 si = rsurface.batchskeletalindex4ub;
9588                 sw = rsurface.batchskeletalweight4ub;
9589                 vp = rsurface.batchvertex3f;
9590                 vs = rsurface.batchsvector3f;
9591                 vt = rsurface.batchtvector3f;
9592                 vn = rsurface.batchnormal3f;
9593                 memset(m[0], 0, sizeof(m));
9594                 memset(n[0], 0, sizeof(n));
9595                 for (i = 0;i < batchnumvertices;i++)
9596                 {
9597                         t[0] = b + si[0]*12;
9598                         if (sw[0] == 255)
9599                         {
9600                                 // common case - only one matrix
9601                                 m[0][0] = t[0][ 0];
9602                                 m[0][1] = t[0][ 1];
9603                                 m[0][2] = t[0][ 2];
9604                                 m[0][3] = t[0][ 3];
9605                                 m[1][0] = t[0][ 4];
9606                                 m[1][1] = t[0][ 5];
9607                                 m[1][2] = t[0][ 6];
9608                                 m[1][3] = t[0][ 7];
9609                                 m[2][0] = t[0][ 8];
9610                                 m[2][1] = t[0][ 9];
9611                                 m[2][2] = t[0][10];
9612                                 m[2][3] = t[0][11];
9613                         }
9614                         else if (sw[2] + sw[3])
9615                         {
9616                                 // blend 4 matrices
9617                                 t[1] = b + si[1]*12;
9618                                 t[2] = b + si[2]*12;
9619                                 t[3] = b + si[3]*12;
9620                                 w[0] = sw[0] * (1.0f / 255.0f);
9621                                 w[1] = sw[1] * (1.0f / 255.0f);
9622                                 w[2] = sw[2] * (1.0f / 255.0f);
9623                                 w[3] = sw[3] * (1.0f / 255.0f);
9624                                 // blend the matrices
9625                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9626                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9627                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9628                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9629                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9630                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9631                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9632                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9633                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9634                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9635                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9636                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9637                         }
9638                         else
9639                         {
9640                                 // blend 2 matrices
9641                                 t[1] = b + si[1]*12;
9642                                 w[0] = sw[0] * (1.0f / 255.0f);
9643                                 w[1] = sw[1] * (1.0f / 255.0f);
9644                                 // blend the matrices
9645                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9646                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9647                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9648                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9649                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9650                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9651                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9652                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9653                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9654                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9655                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9656                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9657                         }
9658                         si += 4;
9659                         sw += 4;
9660                         // modify the vertex
9661                         VectorCopy(vp, tp);
9662                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9663                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9664                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9665                         vp += 3;
9666                         if (vn)
9667                         {
9668                                 // the normal transformation matrix is a set of cross products...
9669                                 CrossProduct(m[1], m[2], n[0]);
9670                                 CrossProduct(m[2], m[0], n[1]);
9671                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9672                                 VectorCopy(vn, tn);
9673                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9674                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9675                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9676                                 VectorNormalize(vn);
9677                                 vn += 3;
9678                                 if (vs)
9679                                 {
9680                                         VectorCopy(vs, ts);
9681                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9682                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9683                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9684                                         VectorNormalize(vs);
9685                                         vs += 3;
9686                                         VectorCopy(vt, tt);
9687                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9688                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9689                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9690                                         VectorNormalize(vt);
9691                                         vt += 3;
9692                                 }
9693                         }
9694                 }
9695                 rsurface.batchskeletaltransform3x4 = NULL;
9696                 rsurface.batchskeletalnumtransforms = 0;
9697         }
9698
9699         // q1bsp surfaces rendered in vertex color mode have to have colors
9700         // calculated based on lightstyles
9701         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9702         {
9703                 // generate color arrays for the surfaces in this list
9704                 int c[4];
9705                 int scale;
9706                 int size3;
9707                 const int *offsets;
9708                 const unsigned char *lm;
9709                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9710                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9711                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9712                 numvertices = 0;
9713                 for (i = 0;i < texturenumsurfaces;i++)
9714                 {
9715                         surface = texturesurfacelist[i];
9716                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9717                         surfacenumvertices = surface->num_vertices;
9718                         if (surface->lightmapinfo->samples)
9719                         {
9720                                 for (j = 0;j < surfacenumvertices;j++)
9721                                 {
9722                                         lm = surface->lightmapinfo->samples + offsets[j];
9723                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9724                                         VectorScale(lm, scale, c);
9725                                         if (surface->lightmapinfo->styles[1] != 255)
9726                                         {
9727                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9728                                                 lm += size3;
9729                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9730                                                 VectorMA(c, scale, lm, c);
9731                                                 if (surface->lightmapinfo->styles[2] != 255)
9732                                                 {
9733                                                         lm += size3;
9734                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9735                                                         VectorMA(c, scale, lm, c);
9736                                                         if (surface->lightmapinfo->styles[3] != 255)
9737                                                         {
9738                                                                 lm += size3;
9739                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9740                                                                 VectorMA(c, scale, lm, c);
9741                                                         }
9742                                                 }
9743                                         }
9744                                         c[0] >>= 7;
9745                                         c[1] >>= 7;
9746                                         c[2] >>= 7;
9747                                         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);
9748                                         numvertices++;
9749                                 }
9750                         }
9751                         else
9752                         {
9753                                 for (j = 0;j < surfacenumvertices;j++)
9754                                 {
9755                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9756                                         numvertices++;
9757                                 }
9758                         }
9759                 }
9760         }
9761
9762         // if vertices are deformed (sprite flares and things in maps, possibly
9763         // water waves, bulges and other deformations), modify the copied vertices
9764         // in place
9765         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9766         {
9767                 float scale;
9768                 switch (deform->deform)
9769                 {
9770                 default:
9771                 case Q3DEFORM_PROJECTIONSHADOW:
9772                 case Q3DEFORM_TEXT0:
9773                 case Q3DEFORM_TEXT1:
9774                 case Q3DEFORM_TEXT2:
9775                 case Q3DEFORM_TEXT3:
9776                 case Q3DEFORM_TEXT4:
9777                 case Q3DEFORM_TEXT5:
9778                 case Q3DEFORM_TEXT6:
9779                 case Q3DEFORM_TEXT7:
9780                 case Q3DEFORM_NONE:
9781                         break;
9782                 case Q3DEFORM_AUTOSPRITE:
9783                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9784                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9785                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9786                         VectorNormalize(newforward);
9787                         VectorNormalize(newright);
9788                         VectorNormalize(newup);
9789 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9790 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9791 //                      rsurface.batchvertex3f_bufferoffset = 0;
9792 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9793 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9794 //                      rsurface.batchsvector3f_bufferoffset = 0;
9795 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9796 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9797 //                      rsurface.batchtvector3f_bufferoffset = 0;
9798 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9799 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9800 //                      rsurface.batchnormal3f_bufferoffset = 0;
9801                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9802                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9803                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9804                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9805                                 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);
9806                         // a single autosprite surface can contain multiple sprites...
9807                         for (j = 0;j < batchnumvertices - 3;j += 4)
9808                         {
9809                                 VectorClear(center);
9810                                 for (i = 0;i < 4;i++)
9811                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9812                                 VectorScale(center, 0.25f, center);
9813                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9814                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9815                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9816                                 for (i = 0;i < 4;i++)
9817                                 {
9818                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9819                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9820                                 }
9821                         }
9822                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9823                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9824                         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);
9825                         break;
9826                 case Q3DEFORM_AUTOSPRITE2:
9827                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9828                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9829                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9830                         VectorNormalize(newforward);
9831                         VectorNormalize(newright);
9832                         VectorNormalize(newup);
9833 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9834 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9835 //                      rsurface.batchvertex3f_bufferoffset = 0;
9836                         {
9837                                 const float *v1, *v2;
9838                                 vec3_t start, end;
9839                                 float f, l;
9840                                 struct
9841                                 {
9842                                         float length2;
9843                                         const float *v1;
9844                                         const float *v2;
9845                                 }
9846                                 shortest[2];
9847                                 memset(shortest, 0, sizeof(shortest));
9848                                 // a single autosprite surface can contain multiple sprites...
9849                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9850                                 {
9851                                         VectorClear(center);
9852                                         for (i = 0;i < 4;i++)
9853                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9854                                         VectorScale(center, 0.25f, center);
9855                                         // find the two shortest edges, then use them to define the
9856                                         // axis vectors for rotating around the central axis
9857                                         for (i = 0;i < 6;i++)
9858                                         {
9859                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9860                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9861                                                 l = VectorDistance2(v1, v2);
9862                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9863                                                 if (v1[2] != v2[2])
9864                                                         l += (1.0f / 1024.0f);
9865                                                 if (shortest[0].length2 > l || i == 0)
9866                                                 {
9867                                                         shortest[1] = shortest[0];
9868                                                         shortest[0].length2 = l;
9869                                                         shortest[0].v1 = v1;
9870                                                         shortest[0].v2 = v2;
9871                                                 }
9872                                                 else if (shortest[1].length2 > l || i == 1)
9873                                                 {
9874                                                         shortest[1].length2 = l;
9875                                                         shortest[1].v1 = v1;
9876                                                         shortest[1].v2 = v2;
9877                                                 }
9878                                         }
9879                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9880                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9881                                         // this calculates the right vector from the shortest edge
9882                                         // and the up vector from the edge midpoints
9883                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9884                                         VectorNormalize(right);
9885                                         VectorSubtract(end, start, up);
9886                                         VectorNormalize(up);
9887                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9888                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9889                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9890                                         VectorNegate(forward, forward);
9891                                         VectorReflect(forward, 0, up, forward);
9892                                         VectorNormalize(forward);
9893                                         CrossProduct(up, forward, newright);
9894                                         VectorNormalize(newright);
9895                                         // rotate the quad around the up axis vector, this is made
9896                                         // especially easy by the fact we know the quad is flat,
9897                                         // so we only have to subtract the center position and
9898                                         // measure distance along the right vector, and then
9899                                         // multiply that by the newright vector and add back the
9900                                         // center position
9901                                         // we also need to subtract the old position to undo the
9902                                         // displacement from the center, which we do with a
9903                                         // DotProduct, the subtraction/addition of center is also
9904                                         // optimized into DotProducts here
9905                                         l = DotProduct(right, center);
9906                                         for (i = 0;i < 4;i++)
9907                                         {
9908                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9909                                                 f = DotProduct(right, v1) - l;
9910                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9911                                         }
9912                                 }
9913                         }
9914                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9915                         {
9916 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9917 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9918 //                              rsurface.batchnormal3f_bufferoffset = 0;
9919                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9920                         }
9921                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9922                         {
9923 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9924 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9925 //                              rsurface.batchsvector3f_bufferoffset = 0;
9926 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9927 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9928 //                              rsurface.batchtvector3f_bufferoffset = 0;
9929                                 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);
9930                         }
9931                         break;
9932                 case Q3DEFORM_NORMAL:
9933                         // deform the normals to make reflections wavey
9934                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9935                         rsurface.batchnormal3f_vertexbuffer = NULL;
9936                         rsurface.batchnormal3f_bufferoffset = 0;
9937                         for (j = 0;j < batchnumvertices;j++)
9938                         {
9939                                 float vertex[3];
9940                                 float *normal = rsurface.batchnormal3f + 3*j;
9941                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9942                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9943                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9944                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9945                                 VectorNormalize(normal);
9946                         }
9947                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9948                         {
9949 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9950 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9951 //                              rsurface.batchsvector3f_bufferoffset = 0;
9952 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9953 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9954 //                              rsurface.batchtvector3f_bufferoffset = 0;
9955                                 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);
9956                         }
9957                         break;
9958                 case Q3DEFORM_WAVE:
9959                         // deform vertex array to make wavey water and flags and such
9960                         waveparms[0] = deform->waveparms[0];
9961                         waveparms[1] = deform->waveparms[1];
9962                         waveparms[2] = deform->waveparms[2];
9963                         waveparms[3] = deform->waveparms[3];
9964                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9965                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9966                         // this is how a divisor of vertex influence on deformation
9967                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9968                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9969 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9970 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9971 //                      rsurface.batchvertex3f_bufferoffset = 0;
9972 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9973 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9974 //                      rsurface.batchnormal3f_bufferoffset = 0;
9975                         for (j = 0;j < batchnumvertices;j++)
9976                         {
9977                                 // if the wavefunc depends on time, evaluate it per-vertex
9978                                 if (waveparms[3])
9979                                 {
9980                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9981                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9982                                 }
9983                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9984                         }
9985                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9986                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9987                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9988                         {
9989 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9991 //                              rsurface.batchsvector3f_bufferoffset = 0;
9992 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9993 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9994 //                              rsurface.batchtvector3f_bufferoffset = 0;
9995                                 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);
9996                         }
9997                         break;
9998                 case Q3DEFORM_BULGE:
9999                         // deform vertex array to make the surface have moving bulges
10000 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10001 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10002 //                      rsurface.batchvertex3f_bufferoffset = 0;
10003 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10004 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10005 //                      rsurface.batchnormal3f_bufferoffset = 0;
10006                         for (j = 0;j < batchnumvertices;j++)
10007                         {
10008                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10009                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10010                         }
10011                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10012                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10013                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10014                         {
10015 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10016 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10017 //                              rsurface.batchsvector3f_bufferoffset = 0;
10018 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10019 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10020 //                              rsurface.batchtvector3f_bufferoffset = 0;
10021                                 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);
10022                         }
10023                         break;
10024                 case Q3DEFORM_MOVE:
10025                         // deform vertex array
10026                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10027                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10028                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10029                         VectorScale(deform->parms, scale, waveparms);
10030 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10031 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10032 //                      rsurface.batchvertex3f_bufferoffset = 0;
10033                         for (j = 0;j < batchnumvertices;j++)
10034                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10035                         break;
10036                 }
10037         }
10038
10039         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10040         {
10041         // generate texcoords based on the chosen texcoord source
10042                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10043                 {
10044                 default:
10045                 case Q3TCGEN_TEXTURE:
10046                         break;
10047                 case Q3TCGEN_LIGHTMAP:
10048         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10049         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10050         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10051                         if (rsurface.batchtexcoordlightmap2f)
10052                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10053                         break;
10054                 case Q3TCGEN_VECTOR:
10055         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10056         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10057         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10058                         for (j = 0;j < batchnumvertices;j++)
10059                         {
10060                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10061                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10062                         }
10063                         break;
10064                 case Q3TCGEN_ENVIRONMENT:
10065                         // make environment reflections using a spheremap
10066                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10067                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10068                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10069                         for (j = 0;j < batchnumvertices;j++)
10070                         {
10071                                 // identical to Q3A's method, but executed in worldspace so
10072                                 // carried models can be shiny too
10073
10074                                 float viewer[3], d, reflected[3], worldreflected[3];
10075
10076                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10077                                 // VectorNormalize(viewer);
10078
10079                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10080
10081                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10082                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10083                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10084                                 // note: this is proportinal to viewer, so we can normalize later
10085
10086                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10087                                 VectorNormalize(worldreflected);
10088
10089                                 // note: this sphere map only uses world x and z!
10090                                 // so positive and negative y will LOOK THE SAME.
10091                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10092                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10093                         }
10094                         break;
10095                 }
10096                 // the only tcmod that needs software vertex processing is turbulent, so
10097                 // check for it here and apply the changes if needed
10098                 // and we only support that as the first one
10099                 // (handling a mixture of turbulent and other tcmods would be problematic
10100                 //  without punting it entirely to a software path)
10101                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10102                 {
10103                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10104                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10105         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10106         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10107         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10108                         for (j = 0;j < batchnumvertices;j++)
10109                         {
10110                                 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);
10111                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10112                         }
10113                 }
10114         }
10115
10116         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10117         {
10118                 // convert the modified arrays to vertex structs
10119 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10120 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10121 //              rsurface.batchvertexmesh_bufferoffset = 0;
10122                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10123                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10124                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10125                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10126                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10127                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10128                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10129                 {
10130                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10131                         {
10132                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10133                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10134                         }
10135                 }
10136                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10137                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10138                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10139                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10140                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10141                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10142                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10143                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10144                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10145                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10146                 {
10147                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10148                         {
10149                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10150                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10151                         }
10152                 }
10153         }
10154
10155         // upload buffer data for the dynamic batch
10156         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10157         {
10158                 if (rsurface.batchvertexmesh)
10159                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10160                 else
10161                 {
10162                         if (rsurface.batchvertex3f)
10163                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10164                         if (rsurface.batchsvector3f)
10165                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10166                         if (rsurface.batchtvector3f)
10167                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10168                         if (rsurface.batchnormal3f)
10169                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10170                         if (rsurface.batchlightmapcolor4f)
10171                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10172                         if (rsurface.batchtexcoordtexture2f)
10173                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10174                         if (rsurface.batchtexcoordlightmap2f)
10175                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10176                         if (rsurface.batchskeletalindex4ub)
10177                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10178                         if (rsurface.batchskeletalweight4ub)
10179                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10180                 }
10181                 if (rsurface.batchelement3s)
10182                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10183                 else if (rsurface.batchelement3i)
10184                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10185         }
10186 }
10187
10188 void RSurf_DrawBatch(void)
10189 {
10190         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10191         // through the pipeline, killing it earlier in the pipeline would have
10192         // per-surface overhead rather than per-batch overhead, so it's best to
10193         // reject it here, before it hits glDraw.
10194         if (rsurface.batchnumtriangles == 0)
10195                 return;
10196 #if 0
10197         // batch debugging code
10198         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10199         {
10200                 int i;
10201                 int j;
10202                 int c;
10203                 const int *e;
10204                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10205                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10206                 {
10207                         c = e[i];
10208                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10209                         {
10210                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10211                                 {
10212                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10213                                                 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);
10214                                         break;
10215                                 }
10216                         }
10217                 }
10218         }
10219 #endif
10220         if (rsurface.batchmultidraw)
10221         {
10222                 // issue multiple draws rather than copying index data
10223                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10224                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10225                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10226                 for (i = 0;i < numsurfaces;)
10227                 {
10228                         // combine consecutive surfaces as one draw
10229                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10230                                 if (surfacelist[j] != surfacelist[k] + 1)
10231                                         break;
10232                         firstvertex = surfacelist[i]->num_firstvertex;
10233                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10234                         firsttriangle = surfacelist[i]->num_firsttriangle;
10235                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10236                         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);
10237                         i = j;
10238                 }
10239         }
10240         else
10241         {
10242                 // there is only one consecutive run of index data (may have been combined)
10243                 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);
10244         }
10245 }
10246
10247 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10248 {
10249         // pick the closest matching water plane
10250         int planeindex, vertexindex, bestplaneindex = -1;
10251         float d, bestd;
10252         vec3_t vert;
10253         const float *v;
10254         r_waterstate_waterplane_t *p;
10255         qboolean prepared = false;
10256         bestd = 0;
10257         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10258         {
10259                 if(p->camera_entity != rsurface.texture->camera_entity)
10260                         continue;
10261                 d = 0;
10262                 if(!prepared)
10263                 {
10264                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10265                         prepared = true;
10266                         if(rsurface.batchnumvertices == 0)
10267                                 break;
10268                 }
10269                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10270                 {
10271                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10272                         d += fabs(PlaneDiff(vert, &p->plane));
10273                 }
10274                 if (bestd > d || bestplaneindex < 0)
10275                 {
10276                         bestd = d;
10277                         bestplaneindex = planeindex;
10278                 }
10279         }
10280         return bestplaneindex;
10281         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10282         // this situation though, as it might be better to render single larger
10283         // batches with useless stuff (backface culled for example) than to
10284         // render multiple smaller batches
10285 }
10286
10287 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10288 {
10289         int i;
10290         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10291         rsurface.passcolor4f_vertexbuffer = 0;
10292         rsurface.passcolor4f_bufferoffset = 0;
10293         for (i = 0;i < rsurface.batchnumvertices;i++)
10294                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10295 }
10296
10297 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10298 {
10299         int i;
10300         float f;
10301         const float *v;
10302         const float *c;
10303         float *c2;
10304         if (rsurface.passcolor4f)
10305         {
10306                 // generate color arrays
10307                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10308                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10309                 rsurface.passcolor4f_vertexbuffer = 0;
10310                 rsurface.passcolor4f_bufferoffset = 0;
10311                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10312                 {
10313                         f = RSurf_FogVertex(v);
10314                         c2[0] = c[0] * f;
10315                         c2[1] = c[1] * f;
10316                         c2[2] = c[2] * f;
10317                         c2[3] = c[3];
10318                 }
10319         }
10320         else
10321         {
10322                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10323                 rsurface.passcolor4f_vertexbuffer = 0;
10324                 rsurface.passcolor4f_bufferoffset = 0;
10325                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10326                 {
10327                         f = RSurf_FogVertex(v);
10328                         c2[0] = f;
10329                         c2[1] = f;
10330                         c2[2] = f;
10331                         c2[3] = 1;
10332                 }
10333         }
10334 }
10335
10336 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10337 {
10338         int i;
10339         float f;
10340         const float *v;
10341         const float *c;
10342         float *c2;
10343         if (!rsurface.passcolor4f)
10344                 return;
10345         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10346         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10347         rsurface.passcolor4f_vertexbuffer = 0;
10348         rsurface.passcolor4f_bufferoffset = 0;
10349         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)
10350         {
10351                 f = RSurf_FogVertex(v);
10352                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10353                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10354                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10355                 c2[3] = c[3];
10356         }
10357 }
10358
10359 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10360 {
10361         int i;
10362         const float *c;
10363         float *c2;
10364         if (!rsurface.passcolor4f)
10365                 return;
10366         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10367         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10368         rsurface.passcolor4f_vertexbuffer = 0;
10369         rsurface.passcolor4f_bufferoffset = 0;
10370         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10371         {
10372                 c2[0] = c[0] * r;
10373                 c2[1] = c[1] * g;
10374                 c2[2] = c[2] * b;
10375                 c2[3] = c[3] * a;
10376         }
10377 }
10378
10379 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10380 {
10381         int i;
10382         const float *c;
10383         float *c2;
10384         if (!rsurface.passcolor4f)
10385                 return;
10386         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10387         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388         rsurface.passcolor4f_vertexbuffer = 0;
10389         rsurface.passcolor4f_bufferoffset = 0;
10390         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10391         {
10392                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10393                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10394                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10395                 c2[3] = c[3];
10396         }
10397 }
10398
10399 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10400 {
10401         // TODO: optimize
10402         rsurface.passcolor4f = NULL;
10403         rsurface.passcolor4f_vertexbuffer = 0;
10404         rsurface.passcolor4f_bufferoffset = 0;
10405         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10406         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10407         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10408         GL_Color(r, g, b, a);
10409         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10410         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10411         R_Mesh_TexMatrix(0, NULL);
10412         RSurf_DrawBatch();
10413 }
10414
10415 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10416 {
10417         // TODO: optimize applyfog && applycolor case
10418         // just apply fog if necessary, and tint the fog color array if necessary
10419         rsurface.passcolor4f = NULL;
10420         rsurface.passcolor4f_vertexbuffer = 0;
10421         rsurface.passcolor4f_bufferoffset = 0;
10422         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10423         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10424         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10425         GL_Color(r, g, b, a);
10426         RSurf_DrawBatch();
10427 }
10428
10429 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10430 {
10431         // TODO: optimize
10432         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10433         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10434         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10435         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10436         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10437         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10438         GL_Color(r, g, b, a);
10439         RSurf_DrawBatch();
10440 }
10441
10442 static void RSurf_DrawBatch_GL11_ClampColor(void)
10443 {
10444         int i;
10445         const float *c1;
10446         float *c2;
10447         if (!rsurface.passcolor4f)
10448                 return;
10449         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10450         {
10451                 c2[0] = bound(0.0f, c1[0], 1.0f);
10452                 c2[1] = bound(0.0f, c1[1], 1.0f);
10453                 c2[2] = bound(0.0f, c1[2], 1.0f);
10454                 c2[3] = bound(0.0f, c1[3], 1.0f);
10455         }
10456 }
10457
10458 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10459 {
10460         int i;
10461         float f;
10462         const float *v;
10463         const float *n;
10464         float *c;
10465         //vec3_t eyedir;
10466
10467         // fake shading
10468         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10469         rsurface.passcolor4f_vertexbuffer = 0;
10470         rsurface.passcolor4f_bufferoffset = 0;
10471         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)
10472         {
10473                 f = -DotProduct(r_refdef.view.forward, n);
10474                 f = max(0, f);
10475                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10476                 f *= fakelightintensity;
10477                 Vector4Set(c, f, f, f, 1);
10478         }
10479 }
10480
10481 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10482 {
10483         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10484         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10485         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10486         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10487         GL_Color(r, g, b, a);
10488         RSurf_DrawBatch();
10489 }
10490
10491 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10492 {
10493         int i;
10494         float f;
10495         float alpha;
10496         const float *v;
10497         const float *n;
10498         float *c;
10499         vec3_t ambientcolor;
10500         vec3_t diffusecolor;
10501         vec3_t lightdir;
10502         // TODO: optimize
10503         // model lighting
10504         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10505         f = 0.5f * lightmapintensity;
10506         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10507         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10508         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10509         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10510         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10511         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10512         alpha = *a;
10513         if (VectorLength2(diffusecolor) > 0)
10514         {
10515                 // q3-style directional shading
10516                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10517                 rsurface.passcolor4f_vertexbuffer = 0;
10518                 rsurface.passcolor4f_bufferoffset = 0;
10519                 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)
10520                 {
10521                         if ((f = DotProduct(n, lightdir)) > 0)
10522                                 VectorMA(ambientcolor, f, diffusecolor, c);
10523                         else
10524                                 VectorCopy(ambientcolor, c);
10525                         c[3] = alpha;
10526                 }
10527                 *r = 1;
10528                 *g = 1;
10529                 *b = 1;
10530                 *a = 1;
10531                 *applycolor = false;
10532         }
10533         else
10534         {
10535                 *r = ambientcolor[0];
10536                 *g = ambientcolor[1];
10537                 *b = ambientcolor[2];
10538                 rsurface.passcolor4f = NULL;
10539                 rsurface.passcolor4f_vertexbuffer = 0;
10540                 rsurface.passcolor4f_bufferoffset = 0;
10541         }
10542 }
10543
10544 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10545 {
10546         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10547         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10548         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10549         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10550         GL_Color(r, g, b, a);
10551         RSurf_DrawBatch();
10552 }
10553
10554 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10555 {
10556         int i;
10557         float f;
10558         const float *v;
10559         float *c;
10560
10561         // fake shading
10562         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10563         rsurface.passcolor4f_vertexbuffer = 0;
10564         rsurface.passcolor4f_bufferoffset = 0;
10565
10566         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10567         {
10568                 f = 1 - RSurf_FogVertex(v);
10569                 c[0] = r;
10570                 c[1] = g;
10571                 c[2] = b;
10572                 c[3] = f * a;
10573         }
10574 }
10575
10576 void RSurf_SetupDepthAndCulling(void)
10577 {
10578         // submodels are biased to avoid z-fighting with world surfaces that they
10579         // may be exactly overlapping (avoids z-fighting artifacts on certain
10580         // doors and things in Quake maps)
10581         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10582         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10583         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10584         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10585 }
10586
10587 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10588 {
10589         int i, j;
10590         // transparent sky would be ridiculous
10591         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10592                 return;
10593         R_SetupShader_Generic_NoTexture(false, false);
10594         skyrenderlater = true;
10595         RSurf_SetupDepthAndCulling();
10596         GL_DepthMask(true);
10597
10598         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10599         if (r_sky_scissor.integer)
10600         {
10601                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10602                 for (i = 0; i < texturenumsurfaces; i++)
10603                 {
10604                         const msurface_t *surf = texturesurfacelist[i];
10605                         const float *v;
10606                         float p[3];
10607                         float mins[3], maxs[3];
10608                         int scissor[4];
10609                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10610                         {
10611                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10612                                 if (j > 0)
10613                                 {
10614                                         if (mins[0] > p[0]) mins[0] = p[0];
10615                                         if (mins[1] > p[1]) mins[1] = p[1];
10616                                         if (mins[2] > p[2]) mins[2] = p[2];
10617                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10618                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10619                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10620                                 }
10621                                 else
10622                                 {
10623                                         VectorCopy(p, mins);
10624                                         VectorCopy(p, maxs);
10625                                 }
10626                         }
10627                         if (!R_ScissorForBBox(mins, maxs, scissor))
10628                         {
10629                                 if (skyscissor[2])
10630                                 {
10631                                         if (skyscissor[0] > scissor[0])
10632                                         {
10633                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10634                                                 skyscissor[0] = scissor[0];
10635                                         }
10636                                         if (skyscissor[1] > scissor[1])
10637                                         {
10638                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10639                                                 skyscissor[1] = scissor[1];
10640                                         }
10641                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10642                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10643                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10644                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10645                                 }
10646                                 else
10647                                         Vector4Copy(scissor, skyscissor);
10648                         }
10649                 }
10650         }
10651
10652         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10653         // skymasking on them, and Quake3 never did sky masking (unlike
10654         // software Quake and software Quake2), so disable the sky masking
10655         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10656         // and skymasking also looks very bad when noclipping outside the
10657         // level, so don't use it then either.
10658         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)
10659         {
10660                 R_Mesh_ResetTextureState();
10661                 if (skyrendermasked)
10662                 {
10663                         R_SetupShader_DepthOrShadow(false, false, false);
10664                         // depth-only (masking)
10665                         GL_ColorMask(0, 0, 0, 0);
10666                         // just to make sure that braindead drivers don't draw
10667                         // anything despite that colormask...
10668                         GL_BlendFunc(GL_ZERO, GL_ONE);
10669                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10670                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10671                 }
10672                 else
10673                 {
10674                         R_SetupShader_Generic_NoTexture(false, false);
10675                         // fog sky
10676                         GL_BlendFunc(GL_ONE, GL_ZERO);
10677                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10678                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10679                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10680                 }
10681                 RSurf_DrawBatch();
10682                 if (skyrendermasked)
10683                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10684         }
10685         R_Mesh_ResetTextureState();
10686         GL_Color(1, 1, 1, 1);
10687 }
10688
10689 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10690 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10691 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10692 {
10693         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10694                 return;
10695         if (prepass)
10696         {
10697                 // render screenspace normalmap to texture
10698                 GL_DepthMask(true);
10699                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10700                 RSurf_DrawBatch();
10701                 return;
10702         }
10703
10704         // bind lightmap texture
10705
10706         // water/refraction/reflection/camera surfaces have to be handled specially
10707         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10708         {
10709                 int start, end, startplaneindex;
10710                 for (start = 0;start < texturenumsurfaces;start = end)
10711                 {
10712                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10713                         if(startplaneindex < 0)
10714                         {
10715                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10716                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10717                                 end = start + 1;
10718                                 continue;
10719                         }
10720                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10721                                 ;
10722                         // now that we have a batch using the same planeindex, render it
10723                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10724                         {
10725                                 // render water or distortion background
10726                                 GL_DepthMask(true);
10727                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10728                                 RSurf_DrawBatch();
10729                                 // blend surface on top
10730                                 GL_DepthMask(false);
10731                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10732                                 RSurf_DrawBatch();
10733                         }
10734                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10735                         {
10736                                 // render surface with reflection texture as input
10737                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10738                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10739                                 RSurf_DrawBatch();
10740                         }
10741                 }
10742                 return;
10743         }
10744
10745         // render surface batch normally
10746         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10747         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10748         RSurf_DrawBatch();
10749 }
10750
10751 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10752 {
10753         // OpenGL 1.3 path - anything not completely ancient
10754         qboolean applycolor;
10755         qboolean applyfog;
10756         int layerindex;
10757         const texturelayer_t *layer;
10758         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);
10759         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10760
10761         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10762         {
10763                 vec4_t layercolor;
10764                 int layertexrgbscale;
10765                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10766                 {
10767                         if (layerindex == 0)
10768                                 GL_AlphaTest(true);
10769                         else
10770                         {
10771                                 GL_AlphaTest(false);
10772                                 GL_DepthFunc(GL_EQUAL);
10773                         }
10774                 }
10775                 GL_DepthMask(layer->depthmask && writedepth);
10776                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10777                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10778                 {
10779                         layertexrgbscale = 4;
10780                         VectorScale(layer->color, 0.25f, layercolor);
10781                 }
10782                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10783                 {
10784                         layertexrgbscale = 2;
10785                         VectorScale(layer->color, 0.5f, layercolor);
10786                 }
10787                 else
10788                 {
10789                         layertexrgbscale = 1;
10790                         VectorScale(layer->color, 1.0f, layercolor);
10791                 }
10792                 layercolor[3] = layer->color[3];
10793                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10794                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10795                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10796                 switch (layer->type)
10797                 {
10798                 case TEXTURELAYERTYPE_LITTEXTURE:
10799                         // single-pass lightmapped texture with 2x rgbscale
10800                         R_Mesh_TexBind(0, r_texture_white);
10801                         R_Mesh_TexMatrix(0, NULL);
10802                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10803                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10804                         R_Mesh_TexBind(1, layer->texture);
10805                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10806                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10807                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10808                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10809                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10810                         else if (FAKELIGHT_ENABLED)
10811                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10812                         else if (rsurface.uselightmaptexture)
10813                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10814                         else
10815                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10816                         break;
10817                 case TEXTURELAYERTYPE_TEXTURE:
10818                         // singletexture unlit texture with transparency support
10819                         R_Mesh_TexBind(0, layer->texture);
10820                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10821                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10822                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10823                         R_Mesh_TexBind(1, 0);
10824                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10825                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10826                         break;
10827                 case TEXTURELAYERTYPE_FOG:
10828                         // singletexture fogging
10829                         if (layer->texture)
10830                         {
10831                                 R_Mesh_TexBind(0, layer->texture);
10832                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10833                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10834                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10835                         }
10836                         else
10837                         {
10838                                 R_Mesh_TexBind(0, 0);
10839                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10840                         }
10841                         R_Mesh_TexBind(1, 0);
10842                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10843                         // generate a color array for the fog pass
10844                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10845                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10846                         RSurf_DrawBatch();
10847                         break;
10848                 default:
10849                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10850                 }
10851         }
10852         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10853         {
10854                 GL_DepthFunc(GL_LEQUAL);
10855                 GL_AlphaTest(false);
10856         }
10857 }
10858
10859 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10860 {
10861         // OpenGL 1.1 - crusty old voodoo path
10862         qboolean applyfog;
10863         int layerindex;
10864         const texturelayer_t *layer;
10865         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);
10866         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10867
10868         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10869         {
10870                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10871                 {
10872                         if (layerindex == 0)
10873                                 GL_AlphaTest(true);
10874                         else
10875                         {
10876                                 GL_AlphaTest(false);
10877                                 GL_DepthFunc(GL_EQUAL);
10878                         }
10879                 }
10880                 GL_DepthMask(layer->depthmask && writedepth);
10881                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10882                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10883                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10884                 switch (layer->type)
10885                 {
10886                 case TEXTURELAYERTYPE_LITTEXTURE:
10887                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10888                         {
10889                                 // two-pass lit texture with 2x rgbscale
10890                                 // first the lightmap pass
10891                                 R_Mesh_TexBind(0, r_texture_white);
10892                                 R_Mesh_TexMatrix(0, NULL);
10893                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10894                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10895                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10896                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10897                                 else if (FAKELIGHT_ENABLED)
10898                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10899                                 else if (rsurface.uselightmaptexture)
10900                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10901                                 else
10902                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10903                                 // then apply the texture to it
10904                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10905                                 R_Mesh_TexBind(0, layer->texture);
10906                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10907                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10908                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10909                                 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);
10910                         }
10911                         else
10912                         {
10913                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10914                                 R_Mesh_TexBind(0, layer->texture);
10915                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10916                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10918                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10919                                         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);
10920                                 else if (FAKELIGHT_ENABLED)
10921                                         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);
10922                                 else
10923                                         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);
10924                         }
10925                         break;
10926                 case TEXTURELAYERTYPE_TEXTURE:
10927                         // singletexture unlit texture with transparency support
10928                         R_Mesh_TexBind(0, layer->texture);
10929                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10930                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10931                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10932                         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);
10933                         break;
10934                 case TEXTURELAYERTYPE_FOG:
10935                         // singletexture fogging
10936                         if (layer->texture)
10937                         {
10938                                 R_Mesh_TexBind(0, layer->texture);
10939                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10940                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10941                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10942                         }
10943                         else
10944                         {
10945                                 R_Mesh_TexBind(0, 0);
10946                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10947                         }
10948                         // generate a color array for the fog pass
10949                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10950                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10951                         RSurf_DrawBatch();
10952                         break;
10953                 default:
10954                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10955                 }
10956         }
10957         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10958         {
10959                 GL_DepthFunc(GL_LEQUAL);
10960                 GL_AlphaTest(false);
10961         }
10962 }
10963
10964 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10965 {
10966         int vi;
10967         int j;
10968         r_vertexgeneric_t *batchvertex;
10969         float c[4];
10970         texture_t *t = rsurface.texture;
10971
10972 //      R_Mesh_ResetTextureState();
10973         R_SetupShader_Generic_NoTexture(false, false);
10974
10975         if(t && t->currentskinframe)
10976         {
10977                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10978                 c[3] *= t->currentalpha;
10979         }
10980         else
10981         {
10982                 c[0] = 1;
10983                 c[1] = 0;
10984                 c[2] = 1;
10985                 c[3] = 1;
10986         }
10987
10988         if (t->pantstexture || t->shirttexture)
10989         {
10990                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10991                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10992                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10993         }
10994
10995         // brighten it up (as texture value 127 means "unlit")
10996         c[0] *= 2 * r_refdef.view.colorscale;
10997         c[1] *= 2 * r_refdef.view.colorscale;
10998         c[2] *= 2 * r_refdef.view.colorscale;
10999
11000         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11001                 c[3] *= r_wateralpha.value;
11002
11003         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11004         {
11005                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11006                 GL_DepthMask(false);
11007         }
11008         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
11009         {
11010                 GL_BlendFunc(GL_ONE, GL_ONE);
11011                 GL_DepthMask(false);
11012         }
11013         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11014         {
11015                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11016                 GL_DepthMask(false);
11017         }
11018         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11019         {
11020                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11021                 GL_DepthMask(false);
11022         }
11023         else
11024         {
11025                 GL_BlendFunc(GL_ONE, GL_ZERO);
11026                 GL_DepthMask(writedepth);
11027         }
11028
11029         if (r_showsurfaces.integer == 3)
11030         {
11031                 rsurface.passcolor4f = NULL;
11032
11033                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11034                 {
11035                         qboolean applycolor = true;
11036                         float one = 1.0;
11037
11038                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11039
11040                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11041                 }
11042                 else if (FAKELIGHT_ENABLED)
11043                 {
11044                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045
11046                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11047                 }
11048                 else
11049                 {
11050                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11051
11052                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11053                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11054                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11055                         RSurf_DrawBatch_GL11_ApplyAmbient();
11056                 }
11057
11058                 if(!rsurface.passcolor4f)
11059                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11060
11061                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11062                 if(r_refdef.fogenabled)
11063                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11064                 RSurf_DrawBatch_GL11_ClampColor();
11065
11066                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11067                 R_SetupShader_Generic_NoTexture(false, false);
11068                 RSurf_DrawBatch();
11069         }
11070         else if (!r_refdef.view.showdebug)
11071         {
11072                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11073                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11074                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11075                 {
11076                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11077                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11078                 }
11079                 R_Mesh_PrepareVertices_Generic_Unlock();
11080                 RSurf_DrawBatch();
11081         }
11082         else if (r_showsurfaces.integer == 4)
11083         {
11084                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11085                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11086                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11087                 {
11088                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11089                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11090                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11091                 }
11092                 R_Mesh_PrepareVertices_Generic_Unlock();
11093                 RSurf_DrawBatch();
11094         }
11095         else if (r_showsurfaces.integer == 2)
11096         {
11097                 const int *e;
11098                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11100                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11101                 {
11102                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11103                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11104                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11105                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11106                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11107                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11108                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11109                 }
11110                 R_Mesh_PrepareVertices_Generic_Unlock();
11111                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11112         }
11113         else
11114         {
11115                 int texturesurfaceindex;
11116                 int k;
11117                 const msurface_t *surface;
11118                 float surfacecolor4f[4];
11119                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11120                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11121                 vi = 0;
11122                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11123                 {
11124                         surface = texturesurfacelist[texturesurfaceindex];
11125                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11126                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11127                         for (j = 0;j < surface->num_vertices;j++)
11128                         {
11129                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11130                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11131                                 vi++;
11132                         }
11133                 }
11134                 R_Mesh_PrepareVertices_Generic_Unlock();
11135                 RSurf_DrawBatch();
11136         }
11137 }
11138
11139 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11140 {
11141         CHECKGLERROR
11142         RSurf_SetupDepthAndCulling();
11143         if (r_showsurfaces.integer)
11144         {
11145                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11146                 return;
11147         }
11148         switch (vid.renderpath)
11149         {
11150         case RENDERPATH_GL20:
11151         case RENDERPATH_D3D9:
11152         case RENDERPATH_D3D10:
11153         case RENDERPATH_D3D11:
11154         case RENDERPATH_SOFT:
11155         case RENDERPATH_GLES2:
11156                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11157                 break;
11158         case RENDERPATH_GL13:
11159         case RENDERPATH_GLES1:
11160                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11161                 break;
11162         case RENDERPATH_GL11:
11163                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11164                 break;
11165         }
11166         CHECKGLERROR
11167 }
11168
11169 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11170 {
11171         int i, j;
11172         int texturenumsurfaces, endsurface;
11173         texture_t *texture;
11174         const msurface_t *surface;
11175         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11176
11177         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11178                 RSurf_ActiveModelEntity(ent, false, false, false);
11179         else
11180         {
11181                 switch (vid.renderpath)
11182                 {
11183                 case RENDERPATH_GL20:
11184                 case RENDERPATH_D3D9:
11185                 case RENDERPATH_D3D10:
11186                 case RENDERPATH_D3D11:
11187                 case RENDERPATH_SOFT:
11188                 case RENDERPATH_GLES2:
11189                         RSurf_ActiveModelEntity(ent, true, true, false);
11190                         break;
11191                 case RENDERPATH_GL11:
11192                 case RENDERPATH_GL13:
11193                 case RENDERPATH_GLES1:
11194                         RSurf_ActiveModelEntity(ent, true, false, false);
11195                         break;
11196                 }
11197         }
11198
11199         if (r_transparentdepthmasking.integer)
11200         {
11201                 qboolean setup = false;
11202                 for (i = 0;i < numsurfaces;i = j)
11203                 {
11204                         j = i + 1;
11205                         surface = rsurface.modelsurfaces + surfacelist[i];
11206                         texture = surface->texture;
11207                         rsurface.texture = R_GetCurrentTexture(texture);
11208                         rsurface.lightmaptexture = NULL;
11209                         rsurface.deluxemaptexture = NULL;
11210                         rsurface.uselightmaptexture = false;
11211                         // scan ahead until we find a different texture
11212                         endsurface = min(i + 1024, numsurfaces);
11213                         texturenumsurfaces = 0;
11214                         texturesurfacelist[texturenumsurfaces++] = surface;
11215                         for (;j < endsurface;j++)
11216                         {
11217                                 surface = rsurface.modelsurfaces + surfacelist[j];
11218                                 if (texture != surface->texture)
11219                                         break;
11220                                 texturesurfacelist[texturenumsurfaces++] = surface;
11221                         }
11222                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11223                                 continue;
11224                         // render the range of surfaces as depth
11225                         if (!setup)
11226                         {
11227                                 setup = true;
11228                                 GL_ColorMask(0,0,0,0);
11229                                 GL_Color(1,1,1,1);
11230                                 GL_DepthTest(true);
11231                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11232                                 GL_DepthMask(true);
11233 //                              R_Mesh_ResetTextureState();
11234                         }
11235                         RSurf_SetupDepthAndCulling();
11236                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11237                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11238                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11239                         RSurf_DrawBatch();
11240                 }
11241                 if (setup)
11242                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11243         }
11244
11245         for (i = 0;i < numsurfaces;i = j)
11246         {
11247                 j = i + 1;
11248                 surface = rsurface.modelsurfaces + surfacelist[i];
11249                 texture = surface->texture;
11250                 rsurface.texture = R_GetCurrentTexture(texture);
11251                 // scan ahead until we find a different texture
11252                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11253                 texturenumsurfaces = 0;
11254                 texturesurfacelist[texturenumsurfaces++] = surface;
11255                 if(FAKELIGHT_ENABLED)
11256                 {
11257                         rsurface.lightmaptexture = NULL;
11258                         rsurface.deluxemaptexture = NULL;
11259                         rsurface.uselightmaptexture = false;
11260                         for (;j < endsurface;j++)
11261                         {
11262                                 surface = rsurface.modelsurfaces + surfacelist[j];
11263                                 if (texture != surface->texture)
11264                                         break;
11265                                 texturesurfacelist[texturenumsurfaces++] = surface;
11266                         }
11267                 }
11268                 else
11269                 {
11270                         rsurface.lightmaptexture = surface->lightmaptexture;
11271                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11272                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11273                         for (;j < endsurface;j++)
11274                         {
11275                                 surface = rsurface.modelsurfaces + surfacelist[j];
11276                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11277                                         break;
11278                                 texturesurfacelist[texturenumsurfaces++] = surface;
11279                         }
11280                 }
11281                 // render the range of surfaces
11282                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11283         }
11284         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11285 }
11286
11287 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11288 {
11289         // transparent surfaces get pushed off into the transparent queue
11290         int surfacelistindex;
11291         const msurface_t *surface;
11292         vec3_t tempcenter, center;
11293         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11294         {
11295                 surface = texturesurfacelist[surfacelistindex];
11296                 if (r_transparent_sortsurfacesbynearest.integer)
11297                 {
11298                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11299                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11300                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11301                 }
11302                 else
11303                 {
11304                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11305                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11306                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11307                 }
11308                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11309                 if (rsurface.entity->transparent_offset) // transparent offset
11310                 {
11311                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11312                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11313                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11314                 }
11315                 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);
11316         }
11317 }
11318
11319 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11320 {
11321         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11322                 return;
11323         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11324                 return;
11325         RSurf_SetupDepthAndCulling();
11326         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11327         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11328         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11329         RSurf_DrawBatch();
11330 }
11331
11332 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11333 {
11334         CHECKGLERROR
11335         if (depthonly)
11336                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11337         else if (prepass)
11338         {
11339                 if (!rsurface.texture->currentnumlayers)
11340                         return;
11341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11342                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11343                 else
11344                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11345         }
11346         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11347                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11348         else if (!rsurface.texture->currentnumlayers)
11349                 return;
11350         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11351         {
11352                 // in the deferred case, transparent surfaces were queued during prepass
11353                 if (!r_shadow_usingdeferredprepass)
11354                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11355         }
11356         else
11357         {
11358                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11359                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11360         }
11361         CHECKGLERROR
11362 }
11363
11364 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11365 {
11366         int i, j;
11367         texture_t *texture;
11368         R_FrameData_SetMark();
11369         // break the surface list down into batches by texture and use of lightmapping
11370         for (i = 0;i < numsurfaces;i = j)
11371         {
11372                 j = i + 1;
11373                 // texture is the base texture pointer, rsurface.texture is the
11374                 // current frame/skin the texture is directing us to use (for example
11375                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11376                 // use skin 1 instead)
11377                 texture = surfacelist[i]->texture;
11378                 rsurface.texture = R_GetCurrentTexture(texture);
11379                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11380                 {
11381                         // if this texture is not the kind we want, skip ahead to the next one
11382                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11383                                 ;
11384                         continue;
11385                 }
11386                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11387                 {
11388                         rsurface.lightmaptexture = NULL;
11389                         rsurface.deluxemaptexture = NULL;
11390                         rsurface.uselightmaptexture = false;
11391                         // simply scan ahead until we find a different texture or lightmap state
11392                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11393                                 ;
11394                 }
11395                 else
11396                 {
11397                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11398                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11399                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11400                         // simply scan ahead until we find a different texture or lightmap state
11401                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11402                                 ;
11403                 }
11404                 // render the range of surfaces
11405                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11406         }
11407         R_FrameData_ReturnToMark();
11408 }
11409
11410 float locboxvertex3f[6*4*3] =
11411 {
11412         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11413         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11414         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11415         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11416         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11417         1,0,0, 0,0,0, 0,1,0, 1,1,0
11418 };
11419
11420 unsigned short locboxelements[6*2*3] =
11421 {
11422          0, 1, 2, 0, 2, 3,
11423          4, 5, 6, 4, 6, 7,
11424          8, 9,10, 8,10,11,
11425         12,13,14, 12,14,15,
11426         16,17,18, 16,18,19,
11427         20,21,22, 20,22,23
11428 };
11429
11430 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11431 {
11432         int i, j;
11433         cl_locnode_t *loc = (cl_locnode_t *)ent;
11434         vec3_t mins, size;
11435         float vertex3f[6*4*3];
11436         CHECKGLERROR
11437         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11438         GL_DepthMask(false);
11439         GL_DepthRange(0, 1);
11440         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11441         GL_DepthTest(true);
11442         GL_CullFace(GL_NONE);
11443         R_EntityMatrix(&identitymatrix);
11444
11445 //      R_Mesh_ResetTextureState();
11446
11447         i = surfacelist[0];
11448         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11449                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11450                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11451                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11452
11453         if (VectorCompare(loc->mins, loc->maxs))
11454         {
11455                 VectorSet(size, 2, 2, 2);
11456                 VectorMA(loc->mins, -0.5f, size, mins);
11457         }
11458         else
11459         {
11460                 VectorCopy(loc->mins, mins);
11461                 VectorSubtract(loc->maxs, loc->mins, size);
11462         }
11463
11464         for (i = 0;i < 6*4*3;)
11465                 for (j = 0;j < 3;j++, i++)
11466                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11467
11468         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11469         R_SetupShader_Generic_NoTexture(false, false);
11470         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11471 }
11472
11473 void R_DrawLocs(void)
11474 {
11475         int index;
11476         cl_locnode_t *loc, *nearestloc;
11477         vec3_t center;
11478         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11479         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11480         {
11481                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11482                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11483         }
11484 }
11485
11486 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11487 {
11488         if (decalsystem->decals)
11489                 Mem_Free(decalsystem->decals);
11490         memset(decalsystem, 0, sizeof(*decalsystem));
11491 }
11492
11493 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)
11494 {
11495         tridecal_t *decal;
11496         tridecal_t *decals;
11497         int i;
11498
11499         // expand or initialize the system
11500         if (decalsystem->maxdecals <= decalsystem->numdecals)
11501         {
11502                 decalsystem_t old = *decalsystem;
11503                 qboolean useshortelements;
11504                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11505                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11506                 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)));
11507                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11508                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11509                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11510                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11511                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11512                 if (decalsystem->numdecals)
11513                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11514                 if (old.decals)
11515                         Mem_Free(old.decals);
11516                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11517                         decalsystem->element3i[i] = i;
11518                 if (useshortelements)
11519                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11520                                 decalsystem->element3s[i] = i;
11521         }
11522
11523         // grab a decal and search for another free slot for the next one
11524         decals = decalsystem->decals;
11525         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11526         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11527                 ;
11528         decalsystem->freedecal = i;
11529         if (decalsystem->numdecals <= i)
11530                 decalsystem->numdecals = i + 1;
11531
11532         // initialize the decal
11533         decal->lived = 0;
11534         decal->triangleindex = triangleindex;
11535         decal->surfaceindex = surfaceindex;
11536         decal->decalsequence = decalsequence;
11537         decal->color4f[0][0] = c0[0];
11538         decal->color4f[0][1] = c0[1];
11539         decal->color4f[0][2] = c0[2];
11540         decal->color4f[0][3] = 1;
11541         decal->color4f[1][0] = c1[0];
11542         decal->color4f[1][1] = c1[1];
11543         decal->color4f[1][2] = c1[2];
11544         decal->color4f[1][3] = 1;
11545         decal->color4f[2][0] = c2[0];
11546         decal->color4f[2][1] = c2[1];
11547         decal->color4f[2][2] = c2[2];
11548         decal->color4f[2][3] = 1;
11549         decal->vertex3f[0][0] = v0[0];
11550         decal->vertex3f[0][1] = v0[1];
11551         decal->vertex3f[0][2] = v0[2];
11552         decal->vertex3f[1][0] = v1[0];
11553         decal->vertex3f[1][1] = v1[1];
11554         decal->vertex3f[1][2] = v1[2];
11555         decal->vertex3f[2][0] = v2[0];
11556         decal->vertex3f[2][1] = v2[1];
11557         decal->vertex3f[2][2] = v2[2];
11558         decal->texcoord2f[0][0] = t0[0];
11559         decal->texcoord2f[0][1] = t0[1];
11560         decal->texcoord2f[1][0] = t1[0];
11561         decal->texcoord2f[1][1] = t1[1];
11562         decal->texcoord2f[2][0] = t2[0];
11563         decal->texcoord2f[2][1] = t2[1];
11564         TriangleNormal(v0, v1, v2, decal->plane);
11565         VectorNormalize(decal->plane);
11566         decal->plane[3] = DotProduct(v0, decal->plane);
11567 }
11568
11569 extern cvar_t cl_decals_bias;
11570 extern cvar_t cl_decals_models;
11571 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11572 // baseparms, parms, temps
11573 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)
11574 {
11575         int cornerindex;
11576         int index;
11577         float v[9][3];
11578         const float *vertex3f;
11579         const float *normal3f;
11580         int numpoints;
11581         float points[2][9][3];
11582         float temp[3];
11583         float tc[9][2];
11584         float f;
11585         float c[9][4];
11586         const int *e;
11587
11588         e = rsurface.modelelement3i + 3*triangleindex;
11589
11590         vertex3f = rsurface.modelvertex3f;
11591         normal3f = rsurface.modelnormal3f;
11592
11593         if (normal3f)
11594         {
11595                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11596                 {
11597                         index = 3*e[cornerindex];
11598                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11599                 }
11600         }
11601         else
11602         {
11603                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11604                 {
11605                         index = 3*e[cornerindex];
11606                         VectorCopy(vertex3f + index, v[cornerindex]);
11607                 }
11608         }
11609
11610         // cull backfaces
11611         //TriangleNormal(v[0], v[1], v[2], normal);
11612         //if (DotProduct(normal, localnormal) < 0.0f)
11613         //      continue;
11614         // clip by each of the box planes formed from the projection matrix
11615         // if anything survives, we emit the decal
11616         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]);
11617         if (numpoints < 3)
11618                 return;
11619         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]);
11620         if (numpoints < 3)
11621                 return;
11622         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]);
11623         if (numpoints < 3)
11624                 return;
11625         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]);
11626         if (numpoints < 3)
11627                 return;
11628         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]);
11629         if (numpoints < 3)
11630                 return;
11631         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]);
11632         if (numpoints < 3)
11633                 return;
11634         // some part of the triangle survived, so we have to accept it...
11635         if (dynamic)
11636         {
11637                 // dynamic always uses the original triangle
11638                 numpoints = 3;
11639                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11640                 {
11641                         index = 3*e[cornerindex];
11642                         VectorCopy(vertex3f + index, v[cornerindex]);
11643                 }
11644         }
11645         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11646         {
11647                 // convert vertex positions to texcoords
11648                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11649                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11650                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11651                 // calculate distance fade from the projection origin
11652                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11653                 f = bound(0.0f, f, 1.0f);
11654                 c[cornerindex][0] = r * f;
11655                 c[cornerindex][1] = g * f;
11656                 c[cornerindex][2] = b * f;
11657                 c[cornerindex][3] = 1.0f;
11658                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11659         }
11660         if (dynamic)
11661                 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);
11662         else
11663                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11664                         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);
11665 }
11666 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)
11667 {
11668         matrix4x4_t projection;
11669         decalsystem_t *decalsystem;
11670         qboolean dynamic;
11671         dp_model_t *model;
11672         const msurface_t *surface;
11673         const msurface_t *surfaces;
11674         const int *surfacelist;
11675         const texture_t *texture;
11676         int numtriangles;
11677         int numsurfacelist;
11678         int surfacelistindex;
11679         int surfaceindex;
11680         int triangleindex;
11681         float localorigin[3];
11682         float localnormal[3];
11683         float localmins[3];
11684         float localmaxs[3];
11685         float localsize;
11686         //float normal[3];
11687         float planes[6][4];
11688         float angles[3];
11689         bih_t *bih;
11690         int bih_triangles_count;
11691         int bih_triangles[256];
11692         int bih_surfaces[256];
11693
11694         decalsystem = &ent->decalsystem;
11695         model = ent->model;
11696         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11697         {
11698                 R_DecalSystem_Reset(&ent->decalsystem);
11699                 return;
11700         }
11701
11702         if (!model->brush.data_leafs && !cl_decals_models.integer)
11703         {
11704                 if (decalsystem->model)
11705                         R_DecalSystem_Reset(decalsystem);
11706                 return;
11707         }
11708
11709         if (decalsystem->model != model)
11710                 R_DecalSystem_Reset(decalsystem);
11711         decalsystem->model = model;
11712
11713         RSurf_ActiveModelEntity(ent, true, false, false);
11714
11715         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11716         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11717         VectorNormalize(localnormal);
11718         localsize = worldsize*rsurface.inversematrixscale;
11719         localmins[0] = localorigin[0] - localsize;
11720         localmins[1] = localorigin[1] - localsize;
11721         localmins[2] = localorigin[2] - localsize;
11722         localmaxs[0] = localorigin[0] + localsize;
11723         localmaxs[1] = localorigin[1] + localsize;
11724         localmaxs[2] = localorigin[2] + localsize;
11725
11726         //VectorCopy(localnormal, planes[4]);
11727         //VectorVectors(planes[4], planes[2], planes[0]);
11728         AnglesFromVectors(angles, localnormal, NULL, false);
11729         AngleVectors(angles, planes[0], planes[2], planes[4]);
11730         VectorNegate(planes[0], planes[1]);
11731         VectorNegate(planes[2], planes[3]);
11732         VectorNegate(planes[4], planes[5]);
11733         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11734         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11735         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11736         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11737         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11738         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11739
11740 #if 1
11741 // works
11742 {
11743         matrix4x4_t forwardprojection;
11744         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11745         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11746 }
11747 #else
11748 // broken
11749 {
11750         float projectionvector[4][3];
11751         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11752         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11753         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11754         projectionvector[0][0] = planes[0][0] * ilocalsize;
11755         projectionvector[0][1] = planes[1][0] * ilocalsize;
11756         projectionvector[0][2] = planes[2][0] * ilocalsize;
11757         projectionvector[1][0] = planes[0][1] * ilocalsize;
11758         projectionvector[1][1] = planes[1][1] * ilocalsize;
11759         projectionvector[1][2] = planes[2][1] * ilocalsize;
11760         projectionvector[2][0] = planes[0][2] * ilocalsize;
11761         projectionvector[2][1] = planes[1][2] * ilocalsize;
11762         projectionvector[2][2] = planes[2][2] * ilocalsize;
11763         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11764         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11765         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11766         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11767 }
11768 #endif
11769
11770         dynamic = model->surfmesh.isanimated;
11771         numsurfacelist = model->nummodelsurfaces;
11772         surfacelist = model->sortedmodelsurfaces;
11773         surfaces = model->data_surfaces;
11774
11775         bih = NULL;
11776         bih_triangles_count = -1;
11777         if(!dynamic)
11778         {
11779                 if(model->render_bih.numleafs)
11780                         bih = &model->render_bih;
11781                 else if(model->collision_bih.numleafs)
11782                         bih = &model->collision_bih;
11783         }
11784         if(bih)
11785                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11786         if(bih_triangles_count == 0)
11787                 return;
11788         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11789                 return;
11790         if(bih_triangles_count > 0)
11791         {
11792                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11793                 {
11794                         surfaceindex = bih_surfaces[triangleindex];
11795                         surface = surfaces + surfaceindex;
11796                         texture = surface->texture;
11797                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11798                                 continue;
11799                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11800                                 continue;
11801                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11802                 }
11803         }
11804         else
11805         {
11806                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11807                 {
11808                         surfaceindex = surfacelist[surfacelistindex];
11809                         surface = surfaces + surfaceindex;
11810                         // check cull box first because it rejects more than any other check
11811                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11812                                 continue;
11813                         // skip transparent surfaces
11814                         texture = surface->texture;
11815                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11816                                 continue;
11817                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11818                                 continue;
11819                         numtriangles = surface->num_triangles;
11820                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11821                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11822                 }
11823         }
11824 }
11825
11826 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11827 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)
11828 {
11829         int renderentityindex;
11830         float worldmins[3];
11831         float worldmaxs[3];
11832         entity_render_t *ent;
11833
11834         if (!cl_decals_newsystem.integer)
11835                 return;
11836
11837         worldmins[0] = worldorigin[0] - worldsize;
11838         worldmins[1] = worldorigin[1] - worldsize;
11839         worldmins[2] = worldorigin[2] - worldsize;
11840         worldmaxs[0] = worldorigin[0] + worldsize;
11841         worldmaxs[1] = worldorigin[1] + worldsize;
11842         worldmaxs[2] = worldorigin[2] + worldsize;
11843
11844         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11845
11846         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11847         {
11848                 ent = r_refdef.scene.entities[renderentityindex];
11849                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11850                         continue;
11851
11852                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11853         }
11854 }
11855
11856 typedef struct r_decalsystem_splatqueue_s
11857 {
11858         vec3_t worldorigin;
11859         vec3_t worldnormal;
11860         float color[4];
11861         float tcrange[4];
11862         float worldsize;
11863         unsigned int decalsequence;
11864 }
11865 r_decalsystem_splatqueue_t;
11866
11867 int r_decalsystem_numqueued = 0;
11868 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11869
11870 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)
11871 {
11872         r_decalsystem_splatqueue_t *queue;
11873
11874         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11875                 return;
11876
11877         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11878         VectorCopy(worldorigin, queue->worldorigin);
11879         VectorCopy(worldnormal, queue->worldnormal);
11880         Vector4Set(queue->color, r, g, b, a);
11881         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11882         queue->worldsize = worldsize;
11883         queue->decalsequence = cl.decalsequence++;
11884 }
11885
11886 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11887 {
11888         int i;
11889         r_decalsystem_splatqueue_t *queue;
11890
11891         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11892                 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);
11893         r_decalsystem_numqueued = 0;
11894 }
11895
11896 extern cvar_t cl_decals_max;
11897 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11898 {
11899         int i;
11900         decalsystem_t *decalsystem = &ent->decalsystem;
11901         int numdecals;
11902         unsigned int killsequence;
11903         tridecal_t *decal;
11904         float frametime;
11905         float lifetime;
11906
11907         if (!decalsystem->numdecals)
11908                 return;
11909
11910         if (r_showsurfaces.integer)
11911                 return;
11912
11913         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11914         {
11915                 R_DecalSystem_Reset(decalsystem);
11916                 return;
11917         }
11918
11919         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11920         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11921
11922         if (decalsystem->lastupdatetime)
11923                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11924         else
11925                 frametime = 0;
11926         decalsystem->lastupdatetime = r_refdef.scene.time;
11927         numdecals = decalsystem->numdecals;
11928
11929         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11930         {
11931                 if (decal->color4f[0][3])
11932                 {
11933                         decal->lived += frametime;
11934                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11935                         {
11936                                 memset(decal, 0, sizeof(*decal));
11937                                 if (decalsystem->freedecal > i)
11938                                         decalsystem->freedecal = i;
11939                         }
11940                 }
11941         }
11942         decal = decalsystem->decals;
11943         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11944                 numdecals--;
11945
11946         // collapse the array by shuffling the tail decals into the gaps
11947         for (;;)
11948         {
11949                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11950                         decalsystem->freedecal++;
11951                 if (decalsystem->freedecal == numdecals)
11952                         break;
11953                 decal[decalsystem->freedecal] = decal[--numdecals];
11954         }
11955
11956         decalsystem->numdecals = numdecals;
11957
11958         if (numdecals <= 0)
11959         {
11960                 // if there are no decals left, reset decalsystem
11961                 R_DecalSystem_Reset(decalsystem);
11962         }
11963 }
11964
11965 extern skinframe_t *decalskinframe;
11966 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11967 {
11968         int i;
11969         decalsystem_t *decalsystem = &ent->decalsystem;
11970         int numdecals;
11971         tridecal_t *decal;
11972         float faderate;
11973         float alpha;
11974         float *v3f;
11975         float *c4f;
11976         float *t2f;
11977         const int *e;
11978         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11979         int numtris = 0;
11980
11981         numdecals = decalsystem->numdecals;
11982         if (!numdecals)
11983                 return;
11984
11985         if (r_showsurfaces.integer)
11986                 return;
11987
11988         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11989         {
11990                 R_DecalSystem_Reset(decalsystem);
11991                 return;
11992         }
11993
11994         // if the model is static it doesn't matter what value we give for
11995         // wantnormals and wanttangents, so this logic uses only rules applicable
11996         // to a model, knowing that they are meaningless otherwise
11997         RSurf_ActiveModelEntity(ent, false, false, false);
11998
11999         decalsystem->lastupdatetime = r_refdef.scene.time;
12000
12001         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12002
12003         // update vertex positions for animated models
12004         v3f = decalsystem->vertex3f;
12005         c4f = decalsystem->color4f;
12006         t2f = decalsystem->texcoord2f;
12007         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12008         {
12009                 if (!decal->color4f[0][3])
12010                         continue;
12011
12012                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12013                         continue;
12014
12015                 // skip backfaces
12016                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12017                         continue;
12018
12019                 // update color values for fading decals
12020                 if (decal->lived >= cl_decals_time.value)
12021                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12022                 else
12023                         alpha = 1.0f;
12024
12025                 c4f[ 0] = decal->color4f[0][0] * alpha;
12026                 c4f[ 1] = decal->color4f[0][1] * alpha;
12027                 c4f[ 2] = decal->color4f[0][2] * alpha;
12028                 c4f[ 3] = 1;
12029                 c4f[ 4] = decal->color4f[1][0] * alpha;
12030                 c4f[ 5] = decal->color4f[1][1] * alpha;
12031                 c4f[ 6] = decal->color4f[1][2] * alpha;
12032                 c4f[ 7] = 1;
12033                 c4f[ 8] = decal->color4f[2][0] * alpha;
12034                 c4f[ 9] = decal->color4f[2][1] * alpha;
12035                 c4f[10] = decal->color4f[2][2] * alpha;
12036                 c4f[11] = 1;
12037
12038                 t2f[0] = decal->texcoord2f[0][0];
12039                 t2f[1] = decal->texcoord2f[0][1];
12040                 t2f[2] = decal->texcoord2f[1][0];
12041                 t2f[3] = decal->texcoord2f[1][1];
12042                 t2f[4] = decal->texcoord2f[2][0];
12043                 t2f[5] = decal->texcoord2f[2][1];
12044
12045                 // update vertex positions for animated models
12046                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12047                 {
12048                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12049                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12050                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12051                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12052                 }
12053                 else
12054                 {
12055                         VectorCopy(decal->vertex3f[0], v3f);
12056                         VectorCopy(decal->vertex3f[1], v3f + 3);
12057                         VectorCopy(decal->vertex3f[2], v3f + 6);
12058                 }
12059
12060                 if (r_refdef.fogenabled)
12061                 {
12062                         alpha = RSurf_FogVertex(v3f);
12063                         VectorScale(c4f, alpha, c4f);
12064                         alpha = RSurf_FogVertex(v3f + 3);
12065                         VectorScale(c4f + 4, alpha, c4f + 4);
12066                         alpha = RSurf_FogVertex(v3f + 6);
12067                         VectorScale(c4f + 8, alpha, c4f + 8);
12068                 }
12069
12070                 v3f += 9;
12071                 c4f += 12;
12072                 t2f += 6;
12073                 numtris++;
12074         }
12075
12076         if (numtris > 0)
12077         {
12078                 r_refdef.stats[r_stat_drawndecals] += numtris;
12079
12080                 // now render the decals all at once
12081                 // (this assumes they all use one particle font texture!)
12082                 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);
12083 //              R_Mesh_ResetTextureState();
12084                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12085                 GL_DepthMask(false);
12086                 GL_DepthRange(0, 1);
12087                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12088                 GL_DepthTest(true);
12089                 GL_CullFace(GL_NONE);
12090                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12091                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12092                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12093         }
12094 }
12095
12096 static void R_DrawModelDecals(void)
12097 {
12098         int i, numdecals;
12099
12100         // fade faster when there are too many decals
12101         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12102         for (i = 0;i < r_refdef.scene.numentities;i++)
12103                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12104
12105         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12106         for (i = 0;i < r_refdef.scene.numentities;i++)
12107                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12108                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12109
12110         R_DecalSystem_ApplySplatEntitiesQueue();
12111
12112         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12113         for (i = 0;i < r_refdef.scene.numentities;i++)
12114                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12115
12116         r_refdef.stats[r_stat_totaldecals] += numdecals;
12117
12118         if (r_showsurfaces.integer)
12119                 return;
12120
12121         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12122
12123         for (i = 0;i < r_refdef.scene.numentities;i++)
12124         {
12125                 if (!r_refdef.viewcache.entityvisible[i])
12126                         continue;
12127                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12128                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12129         }
12130 }
12131
12132 extern cvar_t mod_collision_bih;
12133 static void R_DrawDebugModel(void)
12134 {
12135         entity_render_t *ent = rsurface.entity;
12136         int i, j, flagsmask;
12137         const msurface_t *surface;
12138         dp_model_t *model = ent->model;
12139
12140         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12141                 return;
12142
12143         if (r_showoverdraw.value > 0)
12144         {
12145                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12146                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12147                 R_SetupShader_Generic_NoTexture(false, false);
12148                 GL_DepthTest(false);
12149                 GL_DepthMask(false);
12150                 GL_DepthRange(0, 1);
12151                 GL_BlendFunc(GL_ONE, GL_ONE);
12152                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12153                 {
12154                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12155                                 continue;
12156                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12157                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12158                         {
12159                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12160                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12161                                 if (!rsurface.texture->currentlayers->depthmask)
12162                                         GL_Color(c, 0, 0, 1.0f);
12163                                 else if (ent == r_refdef.scene.worldentity)
12164                                         GL_Color(c, c, c, 1.0f);
12165                                 else
12166                                         GL_Color(0, c, 0, 1.0f);
12167                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12168                                 RSurf_DrawBatch();
12169                         }
12170                 }
12171                 rsurface.texture = NULL;
12172         }
12173
12174         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12175
12176 //      R_Mesh_ResetTextureState();
12177         R_SetupShader_Generic_NoTexture(false, false);
12178         GL_DepthRange(0, 1);
12179         GL_DepthTest(!r_showdisabledepthtest.integer);
12180         GL_DepthMask(false);
12181         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12182
12183         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12184         {
12185                 int triangleindex;
12186                 int bihleafindex;
12187                 qboolean cullbox = false;
12188                 const q3mbrush_t *brush;
12189                 const bih_t *bih = &model->collision_bih;
12190                 const bih_leaf_t *bihleaf;
12191                 float vertex3f[3][3];
12192                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12193                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12194                 {
12195                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12196                                 continue;
12197                         switch (bihleaf->type)
12198                         {
12199                         case BIH_BRUSH:
12200                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12201                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12202                                 {
12203                                         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);
12204                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12205                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12206                                 }
12207                                 break;
12208                         case BIH_COLLISIONTRIANGLE:
12209                                 triangleindex = bihleaf->itemindex;
12210                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12211                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12212                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12213                                 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);
12214                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12215                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12216                                 break;
12217                         case BIH_RENDERTRIANGLE:
12218                                 triangleindex = bihleaf->itemindex;
12219                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12220                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12221                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12222                                 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);
12223                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12224                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12225                                 break;
12226                         }
12227                 }
12228         }
12229
12230         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12231
12232 #ifndef USE_GLES2
12233         if (r_showtris.integer && qglPolygonMode)
12234         {
12235                 if (r_showdisabledepthtest.integer)
12236                 {
12237                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12238                         GL_DepthMask(false);
12239                 }
12240                 else
12241                 {
12242                         GL_BlendFunc(GL_ONE, GL_ZERO);
12243                         GL_DepthMask(true);
12244                 }
12245                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12246                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12247                 {
12248                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12249                                 continue;
12250                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12251                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12252                         {
12253                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12254                                 if (!rsurface.texture->currentlayers->depthmask)
12255                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12256                                 else if (ent == r_refdef.scene.worldentity)
12257                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12258                                 else
12259                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12260                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12261                                 RSurf_DrawBatch();
12262                         }
12263                 }
12264                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12265                 rsurface.texture = NULL;
12266         }
12267
12268         if (r_shownormals.value != 0 && qglBegin)
12269         {
12270                 int l, k;
12271                 vec3_t v;
12272                 if (r_showdisabledepthtest.integer)
12273                 {
12274                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12275                         GL_DepthMask(false);
12276                 }
12277                 else
12278                 {
12279                         GL_BlendFunc(GL_ONE, GL_ZERO);
12280                         GL_DepthMask(true);
12281                 }
12282                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12283                 {
12284                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12285                                 continue;
12286                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12287                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12288                         {
12289                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12290                                 qglBegin(GL_LINES);
12291                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12292                                 {
12293                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12294                                         {
12295                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12296                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12297                                                 qglVertex3f(v[0], v[1], v[2]);
12298                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12299                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12300                                                 qglVertex3f(v[0], v[1], v[2]);
12301                                         }
12302                                 }
12303                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12304                                 {
12305                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12306                                         {
12307                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12308                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12309                                                 qglVertex3f(v[0], v[1], v[2]);
12310                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12311                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12312                                                 qglVertex3f(v[0], v[1], v[2]);
12313                                         }
12314                                 }
12315                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12316                                 {
12317                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12318                                         {
12319                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12320                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12321                                                 qglVertex3f(v[0], v[1], v[2]);
12322                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12323                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12324                                                 qglVertex3f(v[0], v[1], v[2]);
12325                                         }
12326                                 }
12327                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12328                                 {
12329                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12330                                         {
12331                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12332                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12333                                                 qglVertex3f(v[0], v[1], v[2]);
12334                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12335                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12336                                                 qglVertex3f(v[0], v[1], v[2]);
12337                                         }
12338                                 }
12339                                 qglEnd();
12340                                 CHECKGLERROR
12341                         }
12342                 }
12343                 rsurface.texture = NULL;
12344         }
12345 #endif
12346 }
12347
12348 int r_maxsurfacelist = 0;
12349 const msurface_t **r_surfacelist = NULL;
12350 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12351 {
12352         int i, j, endj, flagsmask;
12353         dp_model_t *model = ent->model;
12354         msurface_t *surfaces;
12355         unsigned char *update;
12356         int numsurfacelist = 0;
12357         if (model == NULL)
12358                 return;
12359
12360         if (r_maxsurfacelist < model->num_surfaces)
12361         {
12362                 r_maxsurfacelist = model->num_surfaces;
12363                 if (r_surfacelist)
12364                         Mem_Free((msurface_t **)r_surfacelist);
12365                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12366         }
12367
12368         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12369                 RSurf_ActiveModelEntity(ent, false, false, false);
12370         else if (prepass)
12371                 RSurf_ActiveModelEntity(ent, true, true, true);
12372         else if (depthonly)
12373         {
12374                 switch (vid.renderpath)
12375                 {
12376                 case RENDERPATH_GL20:
12377                 case RENDERPATH_D3D9:
12378                 case RENDERPATH_D3D10:
12379                 case RENDERPATH_D3D11:
12380                 case RENDERPATH_SOFT:
12381                 case RENDERPATH_GLES2:
12382                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12383                         break;
12384                 case RENDERPATH_GL11:
12385                 case RENDERPATH_GL13:
12386                 case RENDERPATH_GLES1:
12387                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12388                         break;
12389                 }
12390         }
12391         else
12392         {
12393                 switch (vid.renderpath)
12394                 {
12395                 case RENDERPATH_GL20:
12396                 case RENDERPATH_D3D9:
12397                 case RENDERPATH_D3D10:
12398                 case RENDERPATH_D3D11:
12399                 case RENDERPATH_SOFT:
12400                 case RENDERPATH_GLES2:
12401                         RSurf_ActiveModelEntity(ent, true, true, false);
12402                         break;
12403                 case RENDERPATH_GL11:
12404                 case RENDERPATH_GL13:
12405                 case RENDERPATH_GLES1:
12406                         RSurf_ActiveModelEntity(ent, true, false, false);
12407                         break;
12408                 }
12409         }
12410
12411         surfaces = model->data_surfaces;
12412         update = model->brushq1.lightmapupdateflags;
12413
12414         // update light styles
12415         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12416         {
12417                 model_brush_lightstyleinfo_t *style;
12418                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12419                 {
12420                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12421                         {
12422                                 int *list = style->surfacelist;
12423                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12424                                 for (j = 0;j < style->numsurfaces;j++)
12425                                         update[list[j]] = true;
12426                         }
12427                 }
12428         }
12429
12430         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12431
12432         if (debug)
12433         {
12434                 R_DrawDebugModel();
12435                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12436                 return;
12437         }
12438
12439         rsurface.lightmaptexture = NULL;
12440         rsurface.deluxemaptexture = NULL;
12441         rsurface.uselightmaptexture = false;
12442         rsurface.texture = NULL;
12443         rsurface.rtlight = NULL;
12444         numsurfacelist = 0;
12445         // add visible surfaces to draw list
12446         if (ent == r_refdef.scene.worldentity)
12447         {
12448                 // for the world entity, check surfacevisible
12449                 for (i = 0;i < model->nummodelsurfaces;i++)
12450                 {
12451                         j = model->sortedmodelsurfaces[i];
12452                         if (r_refdef.viewcache.world_surfacevisible[j])
12453                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12454                 }
12455         }
12456         else
12457         {
12458                 // add all surfaces
12459                 for (i = 0; i < model->nummodelsurfaces; i++)
12460                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12461         }
12462         // don't do anything if there were no surfaces
12463         if (!numsurfacelist)
12464         {
12465                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12466                 return;
12467         }
12468         // update lightmaps if needed
12469         if (update)
12470         {
12471                 int updated = 0;
12472                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12473                 {
12474                         if (update[j])
12475                         {
12476                                 updated++;
12477                                 R_BuildLightMap(ent, surfaces + j);
12478                         }
12479                 }
12480         }
12481
12482         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12483
12484         // add to stats if desired
12485         if (r_speeds.integer && !skysurfaces && !depthonly)
12486         {
12487                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12488                 for (j = 0;j < numsurfacelist;j++)
12489                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12490         }
12491
12492         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12493 }
12494
12495 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12496 {
12497         int q;
12498         static texture_t texture;
12499         static msurface_t surface;
12500         const msurface_t *surfacelist = &surface;
12501
12502         // fake enough texture and surface state to render this geometry
12503
12504         texture.update_lastrenderframe = -1; // regenerate this texture
12505         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12506         texture.basealpha = 1.0f;
12507         texture.currentskinframe = skinframe;
12508         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12509         texture.offsetmapping = OFFSETMAPPING_OFF;
12510         texture.offsetscale = 1;
12511         texture.specularscalemod = 1;
12512         texture.specularpowermod = 1;
12513         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12514         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12515         // JUST GREP FOR "specularscalemod = 1".
12516
12517         for (q = 0; q < 3; q++)
12518         {
12519                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12520                 texture.render_modellight_lightdir[q] = q == 2;
12521                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12522                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12523                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12524                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12525                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12526                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12527                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12528                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12529         }
12530         texture.currentalpha = 1.0f;
12531
12532         surface.texture = &texture;
12533         surface.num_triangles = numtriangles;
12534         surface.num_firsttriangle = firsttriangle;
12535         surface.num_vertices = numvertices;
12536         surface.num_firstvertex = firstvertex;
12537
12538         // now render it
12539         rsurface.texture = R_GetCurrentTexture(surface.texture);
12540         rsurface.lightmaptexture = NULL;
12541         rsurface.deluxemaptexture = NULL;
12542         rsurface.uselightmaptexture = false;
12543         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12544 }
12545
12546 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)
12547 {
12548         static msurface_t surface;
12549         const msurface_t *surfacelist = &surface;
12550
12551         // fake enough texture and surface state to render this geometry
12552         surface.texture = texture;
12553         surface.num_triangles = numtriangles;
12554         surface.num_firsttriangle = firsttriangle;
12555         surface.num_vertices = numvertices;
12556         surface.num_firstvertex = firstvertex;
12557
12558         // now render it
12559         rsurface.texture = R_GetCurrentTexture(surface.texture);
12560         rsurface.lightmaptexture = NULL;
12561         rsurface.deluxemaptexture = NULL;
12562         rsurface.uselightmaptexture = false;
12563         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12564 }