]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added R_SkinFrame_PurgeSkinFrame to de-duplicate some repeated code.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
73 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
74 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
75 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
76 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84
85 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
93 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
94 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
98 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
105 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
106 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
116 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
132 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
133
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
145 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
159 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
160
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169
170 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
171 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
172
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176
177 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
178 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
179 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
183 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
184 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
196 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
199 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
200 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
201 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
202 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
203 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
204 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
205 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
206
207 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
208 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
215 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
216 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
217
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243
244 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
245
246 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
247
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251
252 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
253 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
259
260 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
261
262 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {
265         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
269 };
270
271 extern cvar_t v_glslgamma;
272 extern cvar_t v_glslgamma_2d;
273
274 extern qboolean v_flipped_state;
275
276 r_framebufferstate_t r_fb;
277
278 /// shadow volume bsp struct with automatically growing nodes buffer
279 svbsp_t r_svbsp;
280
281 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
282
283 rtexture_t *r_texture_blanknormalmap;
284 rtexture_t *r_texture_white;
285 rtexture_t *r_texture_grey128;
286 rtexture_t *r_texture_black;
287 rtexture_t *r_texture_notexture;
288 rtexture_t *r_texture_whitecube;
289 rtexture_t *r_texture_normalizationcube;
290 rtexture_t *r_texture_fogattenuation;
291 rtexture_t *r_texture_fogheighttexture;
292 rtexture_t *r_texture_gammaramps;
293 unsigned int r_texture_gammaramps_serial;
294 //rtexture_t *r_texture_fogintensity;
295 rtexture_t *r_texture_reflectcube;
296
297 // TODO: hash lookups?
298 typedef struct cubemapinfo_s
299 {
300         char basename[64];
301         rtexture_t *texture;
302 }
303 cubemapinfo_t;
304
305 int r_texture_numcubemaps;
306 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
307
308 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
309 unsigned int r_numqueries;
310 unsigned int r_maxqueries;
311
312 typedef struct r_qwskincache_s
313 {
314         char name[MAX_QPATH];
315         skinframe_t *skinframe;
316 }
317 r_qwskincache_t;
318
319 static r_qwskincache_t *r_qwskincache;
320 static int r_qwskincache_size;
321
322 /// vertex coordinates for a quad that covers the screen exactly
323 extern const float r_screenvertex3f[12];
324 extern const float r_d3dscreenvertex3f[12];
325 const float r_screenvertex3f[12] =
326 {
327         0, 0, 0,
328         1, 0, 0,
329         1, 1, 0,
330         0, 1, 0
331 };
332 const float r_d3dscreenvertex3f[12] =
333 {
334         0, 1, 0,
335         1, 1, 0,
336         1, 0, 0,
337         0, 0, 0
338 };
339
340 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = in[0] * r;
346                 out[1] = in[1] * g;
347                 out[2] = in[2] * b;
348                 out[3] = in[3];
349                 in += 4;
350                 out += 4;
351         }
352 }
353
354 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
355 {
356         int i;
357         for (i = 0;i < verts;i++)
358         {
359                 out[0] = r;
360                 out[1] = g;
361                 out[2] = b;
362                 out[3] = a;
363                 out += 4;
364         }
365 }
366
367 // FIXME: move this to client?
368 void FOG_clear(void)
369 {
370         if (gamemode == GAME_NEHAHRA)
371         {
372                 Cvar_Set("gl_fogenable", "0");
373                 Cvar_Set("gl_fogdensity", "0.2");
374                 Cvar_Set("gl_fogred", "0.3");
375                 Cvar_Set("gl_foggreen", "0.3");
376                 Cvar_Set("gl_fogblue", "0.3");
377         }
378         r_refdef.fog_density = 0;
379         r_refdef.fog_red = 0;
380         r_refdef.fog_green = 0;
381         r_refdef.fog_blue = 0;
382         r_refdef.fog_alpha = 1;
383         r_refdef.fog_start = 0;
384         r_refdef.fog_end = 16384;
385         r_refdef.fog_height = 1<<30;
386         r_refdef.fog_fadedepth = 128;
387         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
388 }
389
390 static void R_BuildBlankTextures(void)
391 {
392         unsigned char data[4];
393         data[2] = 128; // normal X
394         data[1] = 128; // normal Y
395         data[0] = 255; // normal Z
396         data[3] = 255; // height
397         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 255;
399         data[1] = 255;
400         data[2] = 255;
401         data[3] = 255;
402         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403         data[0] = 128;
404         data[1] = 128;
405         data[2] = 128;
406         data[3] = 255;
407         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
408         data[0] = 0;
409         data[1] = 0;
410         data[2] = 0;
411         data[3] = 255;
412         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildNoTexture(void)
416 {
417         int x, y;
418         unsigned char pix[16][16][4];
419         // this makes a light grey/dark grey checkerboard texture
420         for (y = 0;y < 16;y++)
421         {
422                 for (x = 0;x < 16;x++)
423                 {
424                         if ((y < 8) ^ (x < 8))
425                         {
426                                 pix[y][x][0] = 128;
427                                 pix[y][x][1] = 128;
428                                 pix[y][x][2] = 128;
429                                 pix[y][x][3] = 255;
430                         }
431                         else
432                         {
433                                 pix[y][x][0] = 64;
434                                 pix[y][x][1] = 64;
435                                 pix[y][x][2] = 64;
436                                 pix[y][x][3] = 255;
437                         }
438                 }
439         }
440         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
441 }
442
443 static void R_BuildWhiteCube(void)
444 {
445         unsigned char data[6*1*1*4];
446         memset(data, 255, sizeof(data));
447         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
448 }
449
450 static void R_BuildNormalizationCube(void)
451 {
452         int x, y, side;
453         vec3_t v;
454         vec_t s, t, intensity;
455 #define NORMSIZE 64
456         unsigned char *data;
457         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
458         for (side = 0;side < 6;side++)
459         {
460                 for (y = 0;y < NORMSIZE;y++)
461                 {
462                         for (x = 0;x < NORMSIZE;x++)
463                         {
464                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
466                                 switch(side)
467                                 {
468                                 default:
469                                 case 0:
470                                         v[0] = 1;
471                                         v[1] = -t;
472                                         v[2] = -s;
473                                         break;
474                                 case 1:
475                                         v[0] = -1;
476                                         v[1] = -t;
477                                         v[2] = s;
478                                         break;
479                                 case 2:
480                                         v[0] = s;
481                                         v[1] = 1;
482                                         v[2] = t;
483                                         break;
484                                 case 3:
485                                         v[0] = s;
486                                         v[1] = -1;
487                                         v[2] = -t;
488                                         break;
489                                 case 4:
490                                         v[0] = s;
491                                         v[1] = -t;
492                                         v[2] = 1;
493                                         break;
494                                 case 5:
495                                         v[0] = -s;
496                                         v[1] = -t;
497                                         v[2] = -1;
498                                         break;
499                                 }
500                                 intensity = 127.0f / sqrt(DotProduct(v, v));
501                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
502                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
503                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
504                                 data[((side*64+y)*64+x)*4+3] = 255;
505                         }
506                 }
507         }
508         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
509         Mem_Free(data);
510 }
511
512 static void R_BuildFogTexture(void)
513 {
514         int x, b;
515 #define FOGWIDTH 256
516         unsigned char data1[FOGWIDTH][4];
517         //unsigned char data2[FOGWIDTH][4];
518         double d, r, alpha;
519
520         r_refdef.fogmasktable_start = r_refdef.fog_start;
521         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
522         r_refdef.fogmasktable_range = r_refdef.fogrange;
523         r_refdef.fogmasktable_density = r_refdef.fog_density;
524
525         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
526         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
527         {
528                 d = (x * r - r_refdef.fogmasktable_start);
529                 if(developer_extra.integer)
530                         Con_DPrintf("%f ", d);
531                 d = max(0, d);
532                 if (r_fog_exp2.integer)
533                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
534                 else
535                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
536                 if(developer_extra.integer)
537                         Con_DPrintf(" : %f ", alpha);
538                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
539                 if(developer_extra.integer)
540                         Con_DPrintf(" = %f\n", alpha);
541                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
542         }
543
544         for (x = 0;x < FOGWIDTH;x++)
545         {
546                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
547                 data1[x][0] = b;
548                 data1[x][1] = b;
549                 data1[x][2] = b;
550                 data1[x][3] = 255;
551                 //data2[x][0] = 255 - b;
552                 //data2[x][1] = 255 - b;
553                 //data2[x][2] = 255 - b;
554                 //data2[x][3] = 255;
555         }
556         if (r_texture_fogattenuation)
557         {
558                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
560         }
561         else
562         {
563                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
564                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
565         }
566 }
567
568 static void R_BuildFogHeightTexture(void)
569 {
570         unsigned char *inpixels;
571         int size;
572         int x;
573         int y;
574         int j;
575         float c[4];
576         float f;
577         inpixels = NULL;
578         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
579         if (r_refdef.fogheighttexturename[0])
580                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
581         if (!inpixels)
582         {
583                 r_refdef.fog_height_tablesize = 0;
584                 if (r_texture_fogheighttexture)
585                         R_FreeTexture(r_texture_fogheighttexture);
586                 r_texture_fogheighttexture = NULL;
587                 if (r_refdef.fog_height_table2d)
588                         Mem_Free(r_refdef.fog_height_table2d);
589                 r_refdef.fog_height_table2d = NULL;
590                 if (r_refdef.fog_height_table1d)
591                         Mem_Free(r_refdef.fog_height_table1d);
592                 r_refdef.fog_height_table1d = NULL;
593                 return;
594         }
595         size = image_width;
596         r_refdef.fog_height_tablesize = size;
597         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
598         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
599         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
600         Mem_Free(inpixels);
601         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
602         // average fog color table accounting for every fog layer between a point
603         // and the camera.  (Note: attenuation is handled separately!)
604         for (y = 0;y < size;y++)
605         {
606                 for (x = 0;x < size;x++)
607                 {
608                         Vector4Clear(c);
609                         f = 0;
610                         if (x < y)
611                         {
612                                 for (j = x;j <= y;j++)
613                                 {
614                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
615                                         f++;
616                                 }
617                         }
618                         else
619                         {
620                                 for (j = x;j >= y;j--)
621                                 {
622                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
623                                         f++;
624                                 }
625                         }
626                         f = 1.0f / f;
627                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
630                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
631                 }
632         }
633         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
634 }
635
636 //=======================================================================================================================================================
637
638 static const char *builtinshaderstrings[] =
639 {
640 #include "shader_glsl.h"
641 0
642 };
643
644 const char *builtinhlslshaderstrings[] =
645 {
646 #include "shader_hlsl.h"
647 0
648 };
649
650 //=======================================================================================================================================================
651
652 typedef struct shaderpermutationinfo_s
653 {
654         const char *pretext;
655         const char *name;
656 }
657 shaderpermutationinfo_t;
658
659 typedef struct shadermodeinfo_s
660 {
661         const char *sourcebasename;
662         const char *extension;
663         const char **builtinshaderstrings;
664         const char *pretext;
665         const char *name;
666         char *filename;
667         char *builtinstring;
668         int builtincrc;
669 }
670 shadermodeinfo_t;
671
672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
674 {
675         {"#define USEDIFFUSE\n", " diffuse"},
676         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
677         {"#define USEVIEWTINT\n", " viewtint"},
678         {"#define USECOLORMAPPING\n", " colormapping"},
679         {"#define USESATURATION\n", " saturation"},
680         {"#define USEFOGINSIDE\n", " foginside"},
681         {"#define USEFOGOUTSIDE\n", " fogoutside"},
682         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
683         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
684         {"#define USEGAMMARAMPS\n", " gammaramps"},
685         {"#define USECUBEFILTER\n", " cubefilter"},
686         {"#define USEGLOW\n", " glow"},
687         {"#define USEBLOOM\n", " bloom"},
688         {"#define USESPECULAR\n", " specular"},
689         {"#define USEPOSTPROCESSING\n", " postprocessing"},
690         {"#define USEREFLECTION\n", " reflection"},
691         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
692         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
693         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
694         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
695         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
696         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
697         {"#define USEALPHAKILL\n", " alphakill"},
698         {"#define USEREFLECTCUBE\n", " reflectcube"},
699         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
700         {"#define USEBOUNCEGRID\n", " bouncegrid"},
701         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
702         {"#define USETRIPPY\n", " trippy"},
703         {"#define USEDEPTHRGB\n", " depthrgb"},
704         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
705         {"#define USESKELETAL\n", " skeletal"},
706         {"#define USEOCCLUDE\n", " occlude"}
707 };
708
709 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
710 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
711 {
712         // SHADERLANGUAGE_GLSL
713         {
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731         },
732         // SHADERLANGUAGE_HLSL
733         {
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
750                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
751         },
752 };
753
754 struct r_glsl_permutation_s;
755 typedef struct r_glsl_permutation_s
756 {
757         /// hash lookup data
758         struct r_glsl_permutation_s *hashnext;
759         unsigned int mode;
760         dpuint64 permutation;
761
762         /// indicates if we have tried compiling this permutation already
763         qboolean compiled;
764         /// 0 if compilation failed
765         int program;
766         // texture units assigned to each detected uniform
767         int tex_Texture_First;
768         int tex_Texture_Second;
769         int tex_Texture_GammaRamps;
770         int tex_Texture_Normal;
771         int tex_Texture_Color;
772         int tex_Texture_Gloss;
773         int tex_Texture_Glow;
774         int tex_Texture_SecondaryNormal;
775         int tex_Texture_SecondaryColor;
776         int tex_Texture_SecondaryGloss;
777         int tex_Texture_SecondaryGlow;
778         int tex_Texture_Pants;
779         int tex_Texture_Shirt;
780         int tex_Texture_FogHeightTexture;
781         int tex_Texture_FogMask;
782         int tex_Texture_Lightmap;
783         int tex_Texture_Deluxemap;
784         int tex_Texture_Attenuation;
785         int tex_Texture_Cube;
786         int tex_Texture_Refraction;
787         int tex_Texture_Reflection;
788         int tex_Texture_ShadowMap2D;
789         int tex_Texture_CubeProjection;
790         int tex_Texture_ScreenNormalMap;
791         int tex_Texture_ScreenDiffuse;
792         int tex_Texture_ScreenSpecular;
793         int tex_Texture_ReflectMask;
794         int tex_Texture_ReflectCube;
795         int tex_Texture_BounceGrid;
796         /// locations of detected uniforms in program object, or -1 if not found
797         int loc_Texture_First;
798         int loc_Texture_Second;
799         int loc_Texture_GammaRamps;
800         int loc_Texture_Normal;
801         int loc_Texture_Color;
802         int loc_Texture_Gloss;
803         int loc_Texture_Glow;
804         int loc_Texture_SecondaryNormal;
805         int loc_Texture_SecondaryColor;
806         int loc_Texture_SecondaryGloss;
807         int loc_Texture_SecondaryGlow;
808         int loc_Texture_Pants;
809         int loc_Texture_Shirt;
810         int loc_Texture_FogHeightTexture;
811         int loc_Texture_FogMask;
812         int loc_Texture_Lightmap;
813         int loc_Texture_Deluxemap;
814         int loc_Texture_Attenuation;
815         int loc_Texture_Cube;
816         int loc_Texture_Refraction;
817         int loc_Texture_Reflection;
818         int loc_Texture_ShadowMap2D;
819         int loc_Texture_CubeProjection;
820         int loc_Texture_ScreenNormalMap;
821         int loc_Texture_ScreenDiffuse;
822         int loc_Texture_ScreenSpecular;
823         int loc_Texture_ReflectMask;
824         int loc_Texture_ReflectCube;
825         int loc_Texture_BounceGrid;
826         int loc_Alpha;
827         int loc_BloomBlur_Parameters;
828         int loc_ClientTime;
829         int loc_Color_Ambient;
830         int loc_Color_Diffuse;
831         int loc_Color_Specular;
832         int loc_Color_Glow;
833         int loc_Color_Pants;
834         int loc_Color_Shirt;
835         int loc_DeferredColor_Ambient;
836         int loc_DeferredColor_Diffuse;
837         int loc_DeferredColor_Specular;
838         int loc_DeferredMod_Diffuse;
839         int loc_DeferredMod_Specular;
840         int loc_DistortScaleRefractReflect;
841         int loc_EyePosition;
842         int loc_FogColor;
843         int loc_FogHeightFade;
844         int loc_FogPlane;
845         int loc_FogPlaneViewDist;
846         int loc_FogRangeRecip;
847         int loc_LightColor;
848         int loc_LightDir;
849         int loc_LightPosition;
850         int loc_OffsetMapping_ScaleSteps;
851         int loc_OffsetMapping_LodDistance;
852         int loc_OffsetMapping_Bias;
853         int loc_PixelSize;
854         int loc_ReflectColor;
855         int loc_ReflectFactor;
856         int loc_ReflectOffset;
857         int loc_RefractColor;
858         int loc_Saturation;
859         int loc_ScreenCenterRefractReflect;
860         int loc_ScreenScaleRefractReflect;
861         int loc_ScreenToDepth;
862         int loc_ShadowMap_Parameters;
863         int loc_ShadowMap_TextureScale;
864         int loc_SpecularPower;
865         int loc_Skeletal_Transform12;
866         int loc_UserVec1;
867         int loc_UserVec2;
868         int loc_UserVec3;
869         int loc_UserVec4;
870         int loc_ViewTintColor;
871         int loc_ViewToLight;
872         int loc_ModelToLight;
873         int loc_TexMatrix;
874         int loc_BackgroundTexMatrix;
875         int loc_ModelViewProjectionMatrix;
876         int loc_ModelViewMatrix;
877         int loc_PixelToScreenTexCoord;
878         int loc_ModelToReflectCube;
879         int loc_ShadowMapMatrix;
880         int loc_BloomColorSubtract;
881         int loc_NormalmapScrollBlend;
882         int loc_BounceGridMatrix;
883         int loc_BounceGridIntensity;
884         /// uniform block bindings
885         int ubibind_Skeletal_Transform12_UniformBlock;
886         /// uniform block indices
887         int ubiloc_Skeletal_Transform12_UniformBlock;
888 }
889 r_glsl_permutation_t;
890
891 #define SHADERPERMUTATION_HASHSIZE 256
892
893
894 // non-degradable "lightweight" shader parameters to keep the permutations simpler
895 // these can NOT degrade! only use for simple stuff
896 enum
897 {
898         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
899         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
900         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
903         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
904         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
905         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
906         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
907         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
908         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
909         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
910         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
911         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
912 };
913 #define SHADERSTATICPARMS_COUNT 14
914
915 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
916 static int shaderstaticparms_count = 0;
917
918 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
919 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
920
921 extern qboolean r_shadow_shadowmapsampler;
922 extern int r_shadow_shadowmappcf;
923 qboolean R_CompileShader_CheckStaticParms(void)
924 {
925         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
926         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
927         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
928
929         // detect all
930         if (r_glsl_saturation_redcompensate.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
932         if (r_glsl_vertextextureblend_usebothalphas.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
934         if (r_shadow_glossexact.integer)
935                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
936         if (r_glsl_postprocess.integer)
937         {
938                 if (r_glsl_postprocess_uservec1_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
940                 if (r_glsl_postprocess_uservec2_enable.integer)
941                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
942                 if (r_glsl_postprocess_uservec3_enable.integer)
943                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
944                 if (r_glsl_postprocess_uservec4_enable.integer)
945                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
946         }
947         if (r_fxaa.integer)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
949         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
950                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
951
952         if (r_shadow_shadowmapsampler)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
954         if (r_shadow_shadowmappcf > 1)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
956         else if (r_shadow_shadowmappcf)
957                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
958         if (r_celshading.integer)
959                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
960         if (r_celoutlines.integer)
961                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
962
963         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
964 }
965
966 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
967         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
968                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
969         else \
970                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
971 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
972 {
973         shaderstaticparms_count = 0;
974
975         // emit all
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
989         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
990 }
991
992 /// information about each possible shader permutation
993 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
994 /// currently selected permutation
995 r_glsl_permutation_t *r_glsl_permutation;
996 /// storage for permutations linked in the hash table
997 memexpandablearray_t r_glsl_permutationarray;
998
999 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1000 {
1001         //unsigned int hashdepth = 0;
1002         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1003         r_glsl_permutation_t *p;
1004         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1005         {
1006                 if (p->mode == mode && p->permutation == permutation)
1007                 {
1008                         //if (hashdepth > 10)
1009                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1010                         return p;
1011                 }
1012                 //hashdepth++;
1013         }
1014         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1015         p->mode = mode;
1016         p->permutation = permutation;
1017         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1018         r_glsl_permutationhash[mode][hashindex] = p;
1019         //if (hashdepth > 10)
1020         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1021         return p;
1022 }
1023
1024 static char *R_ShaderStrCat(const char **strings)
1025 {
1026         char *string, *s;
1027         const char **p = strings;
1028         const char *t;
1029         size_t len = 0;
1030         for (p = strings;(t = *p);p++)
1031                 len += strlen(t);
1032         len++;
1033         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1034         len = 0;
1035         for (p = strings;(t = *p);p++)
1036         {
1037                 len = strlen(t);
1038                 memcpy(s, t, len);
1039                 s += len;
1040         }
1041         *s = 0;
1042         return string;
1043 }
1044
1045 static char *R_ShaderStrCat(const char **strings);
1046 static void R_InitShaderModeInfo(void)
1047 {
1048         int i, language;
1049         shadermodeinfo_t *modeinfo;
1050         // 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)
1051         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1052         {
1053                 for (i = 0; i < SHADERMODE_COUNT; i++)
1054                 {
1055                         char filename[MAX_QPATH];
1056                         modeinfo = &shadermodeinfo[language][i];
1057                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1058                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1059                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1060                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1061                 }
1062         }
1063 }
1064
1065 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1066 {
1067         char *shaderstring;
1068         // if the mode has no filename we have to return the builtin string
1069         if (builtinonly || !modeinfo->filename)
1070                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071         // note that FS_LoadFile appends a 0 byte to make it a valid string
1072         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1077                 return shaderstring;
1078         }
1079         // fall back to builtinstring
1080         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1081 }
1082
1083 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1084 {
1085         int i;
1086         int ubibind;
1087         int sampler;
1088         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1089         char *sourcestring;
1090         char permutationname[256];
1091         int vertstrings_count = 0;
1092         int geomstrings_count = 0;
1093         int fragstrings_count = 0;
1094         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1097
1098         if (p->compiled)
1099                 return;
1100         p->compiled = true;
1101         p->program = 0;
1102
1103         permutationname[0] = 0;
1104         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1105
1106         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107
1108         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1109         if(vid.support.glshaderversion >= 140)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117         }
1118         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1119         else if(vid.support.glshaderversion >= 130)
1120         {
1121                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1122                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1123                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1124                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1125                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1126                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1127         }
1128         // if we can do #version 120, we should (this adds the invariant keyword)
1129         else if(vid.support.glshaderversion >= 120)
1130         {
1131                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1132                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1133                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1134                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1135                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1136                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1137         }
1138         // GLES also adds several things from GLSL120
1139         switch(vid.renderpath)
1140         {
1141         case RENDERPATH_GLES2:
1142                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1143                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1144                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1145                 break;
1146         default:
1147                 break;
1148         }
1149
1150         // the first pretext is which type of shader to compile as
1151         // (later these will all be bound together as a program object)
1152         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1153         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1154         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1155
1156         // the second pretext is the mode (for example a light source)
1157         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1158         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1159         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1160         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1161
1162         // now add all the permutation pretexts
1163         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1164         {
1165                 if (permutation & (1ll<<i))
1166                 {
1167                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1170                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1171                 }
1172                 else
1173                 {
1174                         // keep line numbers correct
1175                         vertstrings_list[vertstrings_count++] = "\n";
1176                         geomstrings_list[geomstrings_count++] = "\n";
1177                         fragstrings_list[fragstrings_count++] = "\n";
1178                 }
1179         }
1180
1181         // add static parms
1182         R_CompileShader_AddStaticParms(mode, permutation);
1183         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184         vertstrings_count += shaderstaticparms_count;
1185         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186         geomstrings_count += shaderstaticparms_count;
1187         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1188         fragstrings_count += shaderstaticparms_count;
1189
1190         // now append the shader text itself
1191         vertstrings_list[vertstrings_count++] = sourcestring;
1192         geomstrings_list[geomstrings_count++] = sourcestring;
1193         fragstrings_list[fragstrings_count++] = sourcestring;
1194
1195         // compile the shader program
1196         if (vertstrings_count + geomstrings_count + fragstrings_count)
1197                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1198         if (p->program)
1199         {
1200                 CHECKGLERROR
1201                 qglUseProgram(p->program);CHECKGLERROR
1202                 // look up all the uniform variable names we care about, so we don't
1203                 // have to look them up every time we set them
1204
1205 #if 0
1206                 // debugging aid
1207                 {
1208                         GLint activeuniformindex = 0;
1209                         GLint numactiveuniforms = 0;
1210                         char uniformname[128];
1211                         GLsizei uniformnamelength = 0;
1212                         GLint uniformsize = 0;
1213                         GLenum uniformtype = 0;
1214                         memset(uniformname, 0, sizeof(uniformname));
1215                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1216                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1217                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1218                         {
1219                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1220                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1221                         }
1222                 }
1223 #endif
1224
1225                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1226                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1227                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1228                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1229                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1230                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1231                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1232                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1233                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1234                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1235                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1236                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1237                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1238                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1239                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1240                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1241                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1242                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1243                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1244                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1245                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1246                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1247                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1248                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1249                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1250                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1251                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1252                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1253                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1254                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1255                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1256                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1257                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1258                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1259                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1260                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1261                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1262                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1263                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1264                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1265                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1266                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1267                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1268                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1269                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1270                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1271                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1272                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1273                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1274                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1275                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1276                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1277                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1278                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1279                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1280                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1281                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1282                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1283                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1284                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1285                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1286                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1287                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1288                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1289                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1290                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1291                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1292                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1293                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1294                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1295                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1296                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1297                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1298                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1299                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1300                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1301                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1302                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1303                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1304                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1305                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1306                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1307                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1308                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1309                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1310                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1311                 // initialize the samplers to refer to the texture units we use
1312                 p->tex_Texture_First = -1;
1313                 p->tex_Texture_Second = -1;
1314                 p->tex_Texture_GammaRamps = -1;
1315                 p->tex_Texture_Normal = -1;
1316                 p->tex_Texture_Color = -1;
1317                 p->tex_Texture_Gloss = -1;
1318                 p->tex_Texture_Glow = -1;
1319                 p->tex_Texture_SecondaryNormal = -1;
1320                 p->tex_Texture_SecondaryColor = -1;
1321                 p->tex_Texture_SecondaryGloss = -1;
1322                 p->tex_Texture_SecondaryGlow = -1;
1323                 p->tex_Texture_Pants = -1;
1324                 p->tex_Texture_Shirt = -1;
1325                 p->tex_Texture_FogHeightTexture = -1;
1326                 p->tex_Texture_FogMask = -1;
1327                 p->tex_Texture_Lightmap = -1;
1328                 p->tex_Texture_Deluxemap = -1;
1329                 p->tex_Texture_Attenuation = -1;
1330                 p->tex_Texture_Cube = -1;
1331                 p->tex_Texture_Refraction = -1;
1332                 p->tex_Texture_Reflection = -1;
1333                 p->tex_Texture_ShadowMap2D = -1;
1334                 p->tex_Texture_CubeProjection = -1;
1335                 p->tex_Texture_ScreenNormalMap = -1;
1336                 p->tex_Texture_ScreenDiffuse = -1;
1337                 p->tex_Texture_ScreenSpecular = -1;
1338                 p->tex_Texture_ReflectMask = -1;
1339                 p->tex_Texture_ReflectCube = -1;
1340                 p->tex_Texture_BounceGrid = -1;
1341                 // bind the texture samplers in use
1342                 sampler = 0;
1343                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1344                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1345                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1346                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1347                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1348                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1349                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1353                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1354                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1355                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1356                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1357                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1358                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1359                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1360                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1361                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1362                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1363                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1364                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1365                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1368                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1370                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1371                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1372                 // get the uniform block indices so we can bind them
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374                 if (vid.support.arb_uniform_buffer_object)
1375                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1376                 else
1377 #endif
1378                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1379                 // clear the uniform block bindings
1380                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1381                 // bind the uniform blocks in use
1382                 ubibind = 0;
1383 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1384                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1385 #endif
1386                 // we're done compiling and setting up the shader, at least until it is used
1387                 CHECKGLERROR
1388                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1389         }
1390         else
1391                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1392
1393         // free the strings
1394         if (sourcestring)
1395                 Mem_Free(sourcestring);
1396 }
1397
1398 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1399 {
1400         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1401         if (r_glsl_permutation != perm)
1402         {
1403                 r_glsl_permutation = perm;
1404                 if (!r_glsl_permutation->program)
1405                 {
1406                         if (!r_glsl_permutation->compiled)
1407                         {
1408                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1409                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1410                         }
1411                         if (!r_glsl_permutation->program)
1412                         {
1413                                 // remove features until we find a valid permutation
1414                                 int i;
1415                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1416                                 {
1417                                         // reduce i more quickly whenever it would not remove any bits
1418                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1419                                         if (!(permutation & j))
1420                                                 continue;
1421                                         permutation -= j;
1422                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1423                                         if (!r_glsl_permutation->compiled)
1424                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1425                                         if (r_glsl_permutation->program)
1426                                                 break;
1427                                 }
1428                                 if (i >= SHADERPERMUTATION_COUNT)
1429                                 {
1430                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1431                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1432                                         qglUseProgram(0);CHECKGLERROR
1433                                         return; // no bit left to clear, entire mode is broken
1434                                 }
1435                         }
1436                 }
1437                 CHECKGLERROR
1438                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1439         }
1440         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1441         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1442         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1443         CHECKGLERROR
1444 }
1445
1446 #ifdef SUPPORTD3D
1447
1448 #ifdef SUPPORTD3D
1449 #include <d3d9.h>
1450 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1451 extern D3DCAPS9 vid_d3d9caps;
1452 #endif
1453
1454 struct r_hlsl_permutation_s;
1455 typedef struct r_hlsl_permutation_s
1456 {
1457         /// hash lookup data
1458         struct r_hlsl_permutation_s *hashnext;
1459         unsigned int mode;
1460         dpuint64 permutation;
1461
1462         /// indicates if we have tried compiling this permutation already
1463         qboolean compiled;
1464         /// NULL if compilation failed
1465         IDirect3DVertexShader9 *vertexshader;
1466         IDirect3DPixelShader9 *pixelshader;
1467 }
1468 r_hlsl_permutation_t;
1469
1470 typedef enum D3DVSREGISTER_e
1471 {
1472         D3DVSREGISTER_TexMatrix = 0, // float4x4
1473         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1474         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1475         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1476         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1477         D3DVSREGISTER_ModelToLight = 20, // float4x4
1478         D3DVSREGISTER_EyePosition = 24,
1479         D3DVSREGISTER_FogPlane = 25,
1480         D3DVSREGISTER_LightDir = 26,
1481         D3DVSREGISTER_LightPosition = 27,
1482 }
1483 D3DVSREGISTER_t;
1484
1485 typedef enum D3DPSREGISTER_e
1486 {
1487         D3DPSREGISTER_Alpha = 0,
1488         D3DPSREGISTER_BloomBlur_Parameters = 1,
1489         D3DPSREGISTER_ClientTime = 2,
1490         D3DPSREGISTER_Color_Ambient = 3,
1491         D3DPSREGISTER_Color_Diffuse = 4,
1492         D3DPSREGISTER_Color_Specular = 5,
1493         D3DPSREGISTER_Color_Glow = 6,
1494         D3DPSREGISTER_Color_Pants = 7,
1495         D3DPSREGISTER_Color_Shirt = 8,
1496         D3DPSREGISTER_DeferredColor_Ambient = 9,
1497         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1498         D3DPSREGISTER_DeferredColor_Specular = 11,
1499         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1500         D3DPSREGISTER_DeferredMod_Specular = 13,
1501         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1502         D3DPSREGISTER_EyePosition = 15, // unused
1503         D3DPSREGISTER_FogColor = 16,
1504         D3DPSREGISTER_FogHeightFade = 17,
1505         D3DPSREGISTER_FogPlane = 18,
1506         D3DPSREGISTER_FogPlaneViewDist = 19,
1507         D3DPSREGISTER_FogRangeRecip = 20,
1508         D3DPSREGISTER_LightColor = 21,
1509         D3DPSREGISTER_LightDir = 22, // unused
1510         D3DPSREGISTER_LightPosition = 23,
1511         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1512         D3DPSREGISTER_PixelSize = 25,
1513         D3DPSREGISTER_ReflectColor = 26,
1514         D3DPSREGISTER_ReflectFactor = 27,
1515         D3DPSREGISTER_ReflectOffset = 28,
1516         D3DPSREGISTER_RefractColor = 29,
1517         D3DPSREGISTER_Saturation = 30,
1518         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1519         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1520         D3DPSREGISTER_ScreenToDepth = 33,
1521         D3DPSREGISTER_ShadowMap_Parameters = 34,
1522         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1523         D3DPSREGISTER_SpecularPower = 36,
1524         D3DPSREGISTER_UserVec1 = 37,
1525         D3DPSREGISTER_UserVec2 = 38,
1526         D3DPSREGISTER_UserVec3 = 39,
1527         D3DPSREGISTER_UserVec4 = 40,
1528         D3DPSREGISTER_ViewTintColor = 41,
1529         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1530         D3DPSREGISTER_BloomColorSubtract = 43,
1531         D3DPSREGISTER_ViewToLight = 44, // float4x4
1532         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1533         D3DPSREGISTER_NormalmapScrollBlend = 52,
1534         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1535         D3DPSREGISTER_OffsetMapping_Bias = 54,
1536         // next at 54
1537 }
1538 D3DPSREGISTER_t;
1539
1540 /// information about each possible shader permutation
1541 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1542 /// currently selected permutation
1543 r_hlsl_permutation_t *r_hlsl_permutation;
1544 /// storage for permutations linked in the hash table
1545 memexpandablearray_t r_hlsl_permutationarray;
1546
1547 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1548 {
1549         //unsigned int hashdepth = 0;
1550         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1551         r_hlsl_permutation_t *p;
1552         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1553         {
1554                 if (p->mode == mode && p->permutation == permutation)
1555                 {
1556                         //if (hashdepth > 10)
1557                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1558                         return p;
1559                 }
1560                 //hashdepth++;
1561         }
1562         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1563         p->mode = mode;
1564         p->permutation = permutation;
1565         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1566         r_hlsl_permutationhash[mode][hashindex] = p;
1567         //if (hashdepth > 10)
1568         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1569         return p;
1570 }
1571
1572 #include <d3dx9.h>
1573 //#include <d3dx9shader.h>
1574 //#include <d3dx9mesh.h>
1575
1576 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1577 {
1578         DWORD *vsbin = NULL;
1579         DWORD *psbin = NULL;
1580         fs_offset_t vsbinsize;
1581         fs_offset_t psbinsize;
1582 //      IDirect3DVertexShader9 *vs = NULL;
1583 //      IDirect3DPixelShader9 *ps = NULL;
1584         ID3DXBuffer *vslog = NULL;
1585         ID3DXBuffer *vsbuffer = NULL;
1586         ID3DXConstantTable *vsconstanttable = NULL;
1587         ID3DXBuffer *pslog = NULL;
1588         ID3DXBuffer *psbuffer = NULL;
1589         ID3DXConstantTable *psconstanttable = NULL;
1590         int vsresult = 0;
1591         int psresult = 0;
1592         char temp[MAX_INPUTLINE];
1593         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1594         char vabuf[1024];
1595         qboolean debugshader = gl_paranoid.integer != 0;
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1598         if (!debugshader)
1599         {
1600                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1601                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1602         }
1603         if ((!vsbin && vertstring) || (!psbin && fragstring))
1604         {
1605                 const char* dllnames_d3dx9 [] =
1606                 {
1607                         "d3dx9_43.dll",
1608                         "d3dx9_42.dll",
1609                         "d3dx9_41.dll",
1610                         "d3dx9_40.dll",
1611                         "d3dx9_39.dll",
1612                         "d3dx9_38.dll",
1613                         "d3dx9_37.dll",
1614                         "d3dx9_36.dll",
1615                         "d3dx9_35.dll",
1616                         "d3dx9_34.dll",
1617                         "d3dx9_33.dll",
1618                         "d3dx9_32.dll",
1619                         "d3dx9_31.dll",
1620                         "d3dx9_30.dll",
1621                         "d3dx9_29.dll",
1622                         "d3dx9_28.dll",
1623                         "d3dx9_27.dll",
1624                         "d3dx9_26.dll",
1625                         "d3dx9_25.dll",
1626                         "d3dx9_24.dll",
1627                         NULL
1628                 };
1629                 dllhandle_t d3dx9_dll = NULL;
1630                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1632                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1633                 dllfunction_t d3dx9_dllfuncs[] =
1634                 {
1635                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1636                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1637                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1638                         {NULL, NULL}
1639                 };
1640                 // 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...
1641 #ifndef ID3DXBuffer_GetBufferPointer
1642 #if !defined(__cplusplus) || defined(CINTERFACE)
1643 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1644 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1645 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1646 #else
1647 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1648 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1649 #define ID3DXBuffer_Release(p)            (p)->Release()
1650 #endif
1651 #endif
1652                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1653                 {
1654                         DWORD shaderflags = 0;
1655                         if (debugshader)
1656                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1657                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1658                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1659                         if (vertstring && vertstring[0])
1660                         {
1661                                 if (debugshader)
1662                                 {
1663                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1664                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1665                                 }
1666                                 else
1667                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1668                                 if (vsbuffer)
1669                                 {
1670                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1671                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1672                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1673                                         ID3DXBuffer_Release(vsbuffer);
1674                                 }
1675                                 if (vslog)
1676                                 {
1677                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1678                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1679                                         ID3DXBuffer_Release(vslog);
1680                                 }
1681                         }
1682                         if (fragstring && fragstring[0])
1683                         {
1684                                 if (debugshader)
1685                                 {
1686                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1687                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1688                                 }
1689                                 else
1690                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1691                                 if (psbuffer)
1692                                 {
1693                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1694                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1695                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1696                                         ID3DXBuffer_Release(psbuffer);
1697                                 }
1698                                 if (pslog)
1699                                 {
1700                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1701                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1702                                         ID3DXBuffer_Release(pslog);
1703                                 }
1704                         }
1705                         Sys_UnloadLibrary(&d3dx9_dll);
1706                 }
1707                 else
1708                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1709         }
1710         if (vsbin && psbin)
1711         {
1712                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1713                 if (FAILED(vsresult))
1714                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1715                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1716                 if (FAILED(psresult))
1717                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1718         }
1719         // free the shader data
1720         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1721         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1722 }
1723
1724 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1725 {
1726         int i;
1727         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1728         int vertstring_length = 0;
1729         int geomstring_length = 0;
1730         int fragstring_length = 0;
1731         char *t;
1732         char *sourcestring;
1733         char *vertstring, *geomstring, *fragstring;
1734         char permutationname[256];
1735         char cachename[256];
1736         int vertstrings_count = 0;
1737         int geomstrings_count = 0;
1738         int fragstrings_count = 0;
1739         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1742
1743         if (p->compiled)
1744                 return;
1745         p->compiled = true;
1746         p->vertexshader = NULL;
1747         p->pixelshader = NULL;
1748
1749         permutationname[0] = 0;
1750         cachename[0] = 0;
1751         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1752
1753         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1754         strlcat(cachename, "hlsl/", sizeof(cachename));
1755
1756         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1757         vertstrings_count = 0;
1758         geomstrings_count = 0;
1759         fragstrings_count = 0;
1760         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1761         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1762         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1763
1764         // the first pretext is which type of shader to compile as
1765         // (later these will all be bound together as a program object)
1766         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1767         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1768         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1769
1770         // the second pretext is the mode (for example a light source)
1771         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1772         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1773         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1774         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1775         strlcat(cachename, modeinfo->name, sizeof(cachename));
1776
1777         // now add all the permutation pretexts
1778         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779         {
1780                 if (permutation & (1ll<<i))
1781                 {
1782                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1785                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1786                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1787                 }
1788                 else
1789                 {
1790                         // keep line numbers correct
1791                         vertstrings_list[vertstrings_count++] = "\n";
1792                         geomstrings_list[geomstrings_count++] = "\n";
1793                         fragstrings_list[fragstrings_count++] = "\n";
1794                 }
1795         }
1796
1797         // add static parms
1798         R_CompileShader_AddStaticParms(mode, permutation);
1799         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800         vertstrings_count += shaderstaticparms_count;
1801         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802         geomstrings_count += shaderstaticparms_count;
1803         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1804         fragstrings_count += shaderstaticparms_count;
1805
1806         // replace spaces in the cachename with _ characters
1807         for (i = 0;cachename[i];i++)
1808                 if (cachename[i] == ' ')
1809                         cachename[i] = '_';
1810
1811         // now append the shader text itself
1812         vertstrings_list[vertstrings_count++] = sourcestring;
1813         geomstrings_list[geomstrings_count++] = sourcestring;
1814         fragstrings_list[fragstrings_count++] = sourcestring;
1815
1816         vertstring_length = 0;
1817         for (i = 0;i < vertstrings_count;i++)
1818                 vertstring_length += (int)strlen(vertstrings_list[i]);
1819         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1820         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1821                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1822
1823         geomstring_length = 0;
1824         for (i = 0;i < geomstrings_count;i++)
1825                 geomstring_length += (int)strlen(geomstrings_list[i]);
1826         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1827         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1828                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1829
1830         fragstring_length = 0;
1831         for (i = 0;i < fragstrings_count;i++)
1832                 fragstring_length += (int)strlen(fragstrings_list[i]);
1833         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1834         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1835                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1836
1837         // try to load the cached shader, or generate one
1838         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1839
1840         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1841                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1842         else
1843                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1844
1845         // free the strings
1846         if (vertstring)
1847                 Mem_Free(vertstring);
1848         if (geomstring)
1849                 Mem_Free(geomstring);
1850         if (fragstring)
1851                 Mem_Free(fragstring);
1852         if (sourcestring)
1853                 Mem_Free(sourcestring);
1854 }
1855
1856 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1857 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1858 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);}
1859 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);}
1860 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);}
1861 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);}
1862
1863 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1864 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1865 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);}
1866 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);}
1867 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);}
1868 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);}
1869
1870 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1871 {
1872         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1873         if (r_hlsl_permutation != perm)
1874         {
1875                 r_hlsl_permutation = perm;
1876                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1877                 {
1878                         if (!r_hlsl_permutation->compiled)
1879                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1880                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1881                         {
1882                                 // remove features until we find a valid permutation
1883                                 int i;
1884                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885                                 {
1886                                         // reduce i more quickly whenever it would not remove any bits
1887                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1888                                         if (!(permutation & j))
1889                                                 continue;
1890                                         permutation -= j;
1891                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1892                                         if (!r_hlsl_permutation->compiled)
1893                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1894                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1895                                                 break;
1896                                 }
1897                                 if (i >= SHADERPERMUTATION_COUNT)
1898                                 {
1899                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1900                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1901                                         return; // no bit left to clear, entire mode is broken
1902                                 }
1903                         }
1904                 }
1905                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1906                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1907         }
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1909         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1910         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1911 }
1912 #endif
1913
1914 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1915 {
1916         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1918         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1919         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1920 }
1921
1922 void R_GLSL_Restart_f(void)
1923 {
1924         unsigned int i, limit;
1925         switch(vid.renderpath)
1926         {
1927         case RENDERPATH_D3D9:
1928 #ifdef SUPPORTD3D
1929                 {
1930                         r_hlsl_permutation_t *p;
1931                         r_hlsl_permutation = NULL;
1932                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1933                         for (i = 0;i < limit;i++)
1934                         {
1935                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1936                                 {
1937                                         if (p->vertexshader)
1938                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1939                                         if (p->pixelshader)
1940                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1941                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1942                                 }
1943                         }
1944                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1945                 }
1946 #endif
1947                 break;
1948         case RENDERPATH_D3D10:
1949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950                 break;
1951         case RENDERPATH_D3D11:
1952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_GL20:
1955         case RENDERPATH_GLES2:
1956                 {
1957                         r_glsl_permutation_t *p;
1958                         r_glsl_permutation = NULL;
1959                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1960                         for (i = 0;i < limit;i++)
1961                         {
1962                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1963                                 {
1964                                         GL_Backend_FreeProgram(p->program);
1965                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1966                                 }
1967                         }
1968                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1969                 }
1970                 break;
1971         case RENDERPATH_GL11:
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 break;
1977         }
1978 }
1979
1980 static void R_GLSL_DumpShader_f(void)
1981 {
1982         int i, language, mode, dupe;
1983         char *text;
1984         shadermodeinfo_t *modeinfo;
1985         qfile_t *file;
1986
1987         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1988         {
1989                 modeinfo = shadermodeinfo[language];
1990                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1991                 {
1992                         // don't dump the same file multiple times (most or all shaders come from the same file)
1993                         for (dupe = mode - 1;dupe >= 0;dupe--)
1994                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1995                                         break;
1996                         if (dupe >= 0)
1997                                 continue;
1998                         text = modeinfo[mode].builtinstring;
1999                         if (!text)
2000                                 continue;
2001                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2002                         if (file)
2003                         {
2004                                 FS_Print(file, "/* The engine may define the following macros:\n");
2005                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2006                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2007                                         FS_Print(file, modeinfo[i].pretext);
2008                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2009                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2010                                 FS_Print(file, "*/\n");
2011                                 FS_Print(file, text);
2012                                 FS_Close(file);
2013                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2014                         }
2015                         else
2016                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2017                 }
2018         }
2019 }
2020
2021 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2022 {
2023         dpuint64 permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         permutation |= SHADERPERMUTATION_VIEWTINT;
2027         if (first)
2028                 permutation |= SHADERPERMUTATION_DIFFUSE;
2029         if (second)
2030                 permutation |= SHADERPERMUTATION_SPECULAR;
2031         if (texturemode == GL_MODULATE)
2032                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2033         else if (texturemode == GL_ADD)
2034                 permutation |= SHADERPERMUTATION_GLOW;
2035         else if (texturemode == GL_DECAL)
2036                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2037         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2038                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2039         if (suppresstexalpha)
2040                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2041         if (!second)
2042                 texturemode = GL_MODULATE;
2043         if (vid.allowalphatocoverage)
2044                 GL_AlphaToCoverage(false);
2045         switch (vid.renderpath)
2046         {
2047         case RENDERPATH_D3D9:
2048 #ifdef SUPPORTD3D
2049                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2050                 R_Mesh_TexBind(GL20TU_FIRST , first );
2051                 R_Mesh_TexBind(GL20TU_SECOND, second);
2052                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2054 #endif
2055                 break;
2056         case RENDERPATH_D3D10:
2057                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2058                 break;
2059         case RENDERPATH_D3D11:
2060                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061                 break;
2062         case RENDERPATH_GL20:
2063         case RENDERPATH_GLES2:
2064                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2065                 if (r_glsl_permutation->tex_Texture_First >= 0)
2066                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2067                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2068                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2069                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2070                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, first );
2075                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2076                 R_Mesh_TexMatrix(0, NULL);
2077                 R_Mesh_TexBind(1, second);
2078                 if (second)
2079                 {
2080                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2081                         R_Mesh_TexMatrix(1, NULL);
2082                 }
2083                 break;
2084         case RENDERPATH_GL11:
2085                 R_Mesh_TexBind(0, first );
2086                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2087                 R_Mesh_TexMatrix(0, NULL);
2088                 break;
2089         case RENDERPATH_SOFT:
2090                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2091                 R_Mesh_TexBind(GL20TU_FIRST , first );
2092                 R_Mesh_TexBind(GL20TU_SECOND, second);
2093                 break;
2094         }
2095 }
2096
2097 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2098 {
2099         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2100 }
2101
2102 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2103 {
2104         dpuint64 permutation = 0;
2105         if (r_trippy.integer && !notrippy)
2106                 permutation |= SHADERPERMUTATION_TRIPPY;
2107         if (depthrgb)
2108                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2109         if (skeletal)
2110                 permutation |= SHADERPERMUTATION_SKELETAL;
2111
2112         if (vid.allowalphatocoverage)
2113                 GL_AlphaToCoverage(false);
2114         switch (vid.renderpath)
2115         {
2116         case RENDERPATH_D3D9:
2117 #ifdef SUPPORTD3D
2118                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2119 #endif
2120                 break;
2121         case RENDERPATH_D3D10:
2122                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2123                 break;
2124         case RENDERPATH_D3D11:
2125                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2126                 break;
2127         case RENDERPATH_GL20:
2128         case RENDERPATH_GLES2:
2129                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2130 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2131                 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);
2132 #endif
2133                 break;
2134         case RENDERPATH_GL13:
2135         case RENDERPATH_GLES1:
2136                 R_Mesh_TexBind(0, 0);
2137                 R_Mesh_TexBind(1, 0);
2138                 break;
2139         case RENDERPATH_GL11:
2140                 R_Mesh_TexBind(0, 0);
2141                 break;
2142         case RENDERPATH_SOFT:
2143                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2144                 break;
2145         }
2146 }
2147
2148 extern qboolean r_shadow_usingdeferredprepass;
2149 extern rtexture_t *r_shadow_attenuationgradienttexture;
2150 extern rtexture_t *r_shadow_attenuation2dtexture;
2151 extern rtexture_t *r_shadow_attenuation3dtexture;
2152 extern qboolean r_shadow_usingshadowmap2d;
2153 extern qboolean r_shadow_usingshadowmaportho;
2154 extern float r_shadow_modelshadowmap_texturescale[4];
2155 extern float r_shadow_modelshadowmap_parameters[4];
2156 extern float r_shadow_lightshadowmap_texturescale[4];
2157 extern float r_shadow_lightshadowmap_parameters[4];
2158 extern qboolean r_shadow_shadowmapvsdct;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2160 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2161 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2162 extern matrix4x4_t r_shadow_shadowmapmatrix;
2163 extern int r_shadow_prepass_width;
2164 extern int r_shadow_prepass_height;
2165 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2166 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2167 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2168 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2169
2170 #define BLENDFUNC_ALLOWS_COLORMOD      1
2171 #define BLENDFUNC_ALLOWS_FOG           2
2172 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2173 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2174 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2175 static int R_BlendFuncFlags(int src, int dst)
2176 {
2177         int r = 0;
2178
2179         // a blendfunc allows colormod if:
2180         // a) it can never keep the destination pixel invariant, or
2181         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2182         // this is to prevent unintended side effects from colormod
2183
2184         // a blendfunc allows fog if:
2185         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2186         // this is to prevent unintended side effects from fog
2187
2188         // these checks are the output of fogeval.pl
2189
2190         r |= BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2200         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2202         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2206         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2209         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2211         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2212
2213         return r;
2214 }
2215
2216 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)
2217 {
2218         // select a permutation of the lighting shader appropriate to this
2219         // combination of texture, entity, light source, and fogging, only use the
2220         // minimum features necessary to avoid wasting rendering time in the
2221         // fragment shader on features that are not being used
2222         dpuint64 permutation = 0;
2223         unsigned int mode = 0;
2224         int blendfuncflags;
2225         texture_t *t = rsurface.texture;
2226         float m16f[16];
2227         matrix4x4_t tempmatrix;
2228         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2229         if (r_trippy.integer && !notrippy)
2230                 permutation |= SHADERPERMUTATION_TRIPPY;
2231         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2232                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2233         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2234                 permutation |= SHADERPERMUTATION_OCCLUDE;
2235         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2236                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2237         if (rsurfacepass == RSURFPASS_BACKGROUND)
2238         {
2239                 // distorted background
2240                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2241                 {
2242                         mode = SHADERMODE_WATER;
2243                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2246                         {
2247                                 // this is the right thing to do for wateralpha
2248                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2249                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2250                         }
2251                         else
2252                         {
2253                                 // this is the right thing to do for entity alpha
2254                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                         }
2257                 }
2258                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2259                 {
2260                         mode = SHADERMODE_REFRACTION;
2261                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265                 }
2266                 else
2267                 {
2268                         mode = SHADERMODE_GENERIC;
2269                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2270                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2272                 }
2273                 if (vid.allowalphatocoverage)
2274                         GL_AlphaToCoverage(false);
2275         }
2276         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2277         {
2278                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2279                 {
2280                         switch(t->offsetmapping)
2281                         {
2282                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_OFF: break;
2286                         }
2287                 }
2288                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290                 // normalmap (deferred prepass), may use alpha test on diffuse
2291                 mode = SHADERMODE_DEFERREDGEOMETRY;
2292                 GL_BlendFunc(GL_ONE, GL_ZERO);
2293                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2294                 if (vid.allowalphatocoverage)
2295                         GL_AlphaToCoverage(false);
2296         }
2297         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2298         {
2299                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2300                 {
2301                         switch(t->offsetmapping)
2302                         {
2303                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2304                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_OFF: break;
2307                         }
2308                 }
2309                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2310                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2311                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2312                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2313                 // light source
2314                 mode = SHADERMODE_LIGHTSOURCE;
2315                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2316                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2317                 if (VectorLength2(rtlightdiffuse) > 0)
2318                         permutation |= SHADERPERMUTATION_DIFFUSE;
2319                 if (VectorLength2(rtlightspecular) > 0)
2320                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2321                 if (r_refdef.fogenabled)
2322                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323                 if (t->colormapping)
2324                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2325                 if (r_shadow_usingshadowmap2d)
2326                 {
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328                         if(r_shadow_shadowmapvsdct)
2329                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2330
2331                         if (r_shadow_shadowmap2ddepthbuffer)
2332                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2333                 }
2334                 if (t->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2337                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2338                 if (vid.allowalphatocoverage)
2339                         GL_AlphaToCoverage(false);
2340         }
2341         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2344                 {
2345                         switch(t->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2356                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2357                 // directional model lighting
2358                 mode = SHADERMODE_LIGHTDIRECTION;
2359                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360                         permutation |= SHADERPERMUTATION_GLOW;
2361                 if (VectorLength2(t->render_modellight_diffuse))
2362                         permutation |= SHADERPERMUTATION_DIFFUSE;
2363                 if (VectorLength2(t->render_modellight_specular) > 0)
2364                         permutation |= SHADERPERMUTATION_SPECULAR;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (t->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmap2ddepthbuffer)
2375                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2376                 }
2377                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378                         permutation |= SHADERPERMUTATION_REFLECTION;
2379                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2380                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381                 if (t->reflectmasktexture)
2382                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2384                 {
2385                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2386                         if (r_shadow_bouncegrid_state.directional)
2387                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2388                 }
2389                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2390                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2391                 // when using alphatocoverage, we don't need alphakill
2392                 if (vid.allowalphatocoverage)
2393                 {
2394                         if (r_transparent_alphatocoverage.integer)
2395                         {
2396                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2397                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2398                         }
2399                         else
2400                                 GL_AlphaToCoverage(false);
2401                 }
2402         }
2403         else
2404         {
2405                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2406                 {
2407                         switch(t->offsetmapping)
2408                         {
2409                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2410                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412                         case OFFSETMAPPING_OFF: break;
2413                         }
2414                 }
2415                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2416                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2417                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2418                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2419                 // lightmapped wall
2420                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2421                         permutation |= SHADERPERMUTATION_GLOW;
2422                 if (r_refdef.fogenabled)
2423                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2424                 if (t->colormapping)
2425                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2426                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2427                 {
2428                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2429                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2430
2431                         if (r_shadow_shadowmap2ddepthbuffer)
2432                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2433                 }
2434                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (t->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (VectorLength2(t->render_lightmap_specular) > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (VectorLength2(t->render_lightmap_specular) > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         if (rsurface.uselightmaptexture)
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2464                         else
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2466                         permutation |= SHADERPERMUTATION_DIFFUSE;
2467                         if (VectorLength2(t->render_lightmap_specular) > 0)
2468                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469                 }
2470                 else if (rsurface.uselightmaptexture)
2471                 {
2472                         // ordinary lightmapping (q1bsp, q3bsp)
2473                         mode = SHADERMODE_LIGHTMAP;
2474                 }
2475                 else
2476                 {
2477                         // ordinary vertex coloring (q3bsp)
2478                         mode = SHADERMODE_VERTEXCOLOR;
2479                 }
2480                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2481                 {
2482                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2483                         if (r_shadow_bouncegrid_state.directional)
2484                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485                 }
2486                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2487                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2488                 // when using alphatocoverage, we don't need alphakill
2489                 if (vid.allowalphatocoverage)
2490                 {
2491                         if (r_transparent_alphatocoverage.integer)
2492                         {
2493                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2494                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2495                         }
2496                         else
2497                                 GL_AlphaToCoverage(false);
2498                 }
2499         }
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504         switch(vid.renderpath)
2505         {
2506         case RENDERPATH_D3D9:
2507 #ifdef SUPPORTD3D
2508                 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);
2509                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2510                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512                 if (mode == SHADERMODE_LIGHTSOURCE)
2513                 {
2514                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2516                 }
2517                 else
2518                 {
2519                         if (mode == SHADERMODE_LIGHTDIRECTION)
2520                         {
2521                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2522                         }
2523                 }
2524                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2529
2530                 if (mode == SHADERMODE_LIGHTSOURCE)
2531                 {
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2537
2538                         // additive passes are only darkened by fog, not tinted
2539                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2541                 }
2542                 else
2543                 {
2544                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2546                         if (mode == SHADERMODE_FLATCOLOR)
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2549                         }
2550                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2551                         {
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2557                         }
2558                         else
2559                         {
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2563                         }
2564                         // additive passes are only darkened by fog, not tinted
2565                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         else
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569                         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);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577                         if (mode == SHADERMODE_WATER)
2578                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2579                 }
2580                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2581                 {
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2584                 }
2585                 else
2586                 {
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2589                 }
2590                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2591                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2592                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2593                 if (t->pantstexture)
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2595                 else
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2597                 if (t->shirttexture)
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2599                 else
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2601                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2603                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2605                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2606                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2607                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2608                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2609                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2610                         );
2611                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2613                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2614                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2615
2616                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2617                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2618                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2619                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2625                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2627                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2628                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2629                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2630                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2631                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2632                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2633                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2634                 {
2635                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2636                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2637                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638                 }
2639                 else
2640                 {
2641                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2642                 }
2643 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2645                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2646                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2647                 {
2648                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2649                         if (rsurface.rtlight)
2650                         {
2651                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2652                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2653                         }
2654                 }
2655 #endif
2656                 break;
2657         case RENDERPATH_D3D10:
2658                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659                 break;
2660         case RENDERPATH_D3D11:
2661                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_GL20:
2664         case RENDERPATH_GLES2:
2665                 if (!vid.useinterleavedarrays)
2666                 {
2667                         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);
2668                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2669                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2676                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2677                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2678                 }
2679                 else
2680                 {
2681                         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);
2682                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2683                 }
2684                 // this has to be after RSurf_PrepareVerticesForBatch
2685                 if (rsurface.batchskeletaltransform3x4buffer)
2686                         permutation |= SHADERPERMUTATION_SKELETAL;
2687                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2688 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2689                 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);
2690 #endif
2691                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692                 if (mode == SHADERMODE_LIGHTSOURCE)
2693                 {
2694                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2697                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2698                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2699                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2700         
2701                         // additive passes are only darkened by fog, not tinted
2702                         if (r_glsl_permutation->loc_FogColor >= 0)
2703                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704                         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);
2705                 }
2706                 else
2707                 {
2708                         if (mode == SHADERMODE_FLATCOLOR)
2709                         {
2710                                 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]);
2711                         }
2712                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2713                         {
2714                                 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]);
2715                                 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]);
2716                                 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]);
2717                                 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]);
2718                                 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]);
2719                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2720                                 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]);
2721                         }
2722                         else
2723                         {
2724                                 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]);
2725                                 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]);
2726                                 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]);
2727                                 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]);
2728                                 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]);
2729                         }
2730                         // additive passes are only darkened by fog, not tinted
2731                         if (r_glsl_permutation->loc_FogColor >= 0)
2732                         {
2733                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2735                                 else
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2737                         }
2738                         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);
2739                         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]);
2740                         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]);
2741                         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);
2742                         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);
2743                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2744                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2745                         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);
2746                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2747                 }
2748                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2752                 {
2753                         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]);
2754                         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]);
2755                 }
2756                 else
2757                 {
2758                         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]);
2759                         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]);
2760                 }
2761
2762                 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]);
2763                 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));
2764                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2765                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2766                 {
2767                         if (t->pantstexture)
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2769                         else
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2771                 }
2772                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2773                 {
2774                         if (t->shirttexture)
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2776                         else
2777                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2778                 }
2779                 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]);
2780                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2781                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2782                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2783                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2784                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2785                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2786                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2787                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2788                         );
2789                 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);
2790                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2791                 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]);
2792                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2793                 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);}
2794                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2795
2796                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2797                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2798                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2799                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2800                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2801                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2802                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2807                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2808                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2809                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2810                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2811                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2812                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2813                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2814                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2815                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2816                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2817                 {
2818                         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);
2819                         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);
2820                         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);
2821                 }
2822                 else
2823                 {
2824                         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);
2825                 }
2826                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2827                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2828                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2829                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2830                 {
2831                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2832                         if (rsurface.rtlight)
2833                         {
2834                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2835                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2836                         }
2837                 }
2838                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2839                 CHECKGLERROR
2840                 break;
2841         case RENDERPATH_GL11:
2842         case RENDERPATH_GL13:
2843         case RENDERPATH_GLES1:
2844                 break;
2845         case RENDERPATH_SOFT:
2846                 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);
2847                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2848                 R_SetupShader_SetPermutationSoft(mode, permutation);
2849                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2850                 if (mode == SHADERMODE_LIGHTSOURCE)
2851                 {
2852                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2858         
2859                         // additive passes are only darkened by fog, not tinted
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2861                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2862                 }
2863                 else
2864                 {
2865                         if (mode == SHADERMODE_FLATCOLOR)
2866                         {
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2868                         }
2869                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2876                         }
2877                         else
2878                         {
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2882                         }
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2885                         // additive passes are only darkened by fog, not tinted
2886                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2888                         else
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2890                         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);
2891                         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]);
2892                         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]);
2893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2896                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2897                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2898                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2899                 }
2900                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2901                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2902                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2903                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2904                 {
2905                         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]);
2906                         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]);
2907                 }
2908                 else
2909                 {
2910                         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]);
2911                         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]);
2912                 }
2913
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2916                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2917                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2918                 {
2919                         if (t->pantstexture)
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2921                         else
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2923                 }
2924                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2925                 {
2926                         if (t->shirttexture)
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2928                         else
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2930                 }
2931                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2934                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2935                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2936                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2937                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2939                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2940                         );
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2942                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2943                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2945
2946                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2947                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2948                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2949                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2955                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2957                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2958                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2959                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2960                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2961                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2962                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2963                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2964                 {
2965                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2966                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2967                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2968                 }
2969                 else
2970                 {
2971                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2972                 }
2973 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2974                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2975                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2976                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2977                 {
2978                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2979                         if (rsurface.rtlight)
2980                         {
2981                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2982                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2983                         }
2984                 }
2985                 break;
2986         }
2987 }
2988
2989 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2990 {
2991         // select a permutation of the lighting shader appropriate to this
2992         // combination of texture, entity, light source, and fogging, only use the
2993         // minimum features necessary to avoid wasting rendering time in the
2994         // fragment shader on features that are not being used
2995         dpuint64 permutation = 0;
2996         unsigned int mode = 0;
2997         const float *lightcolorbase = rtlight->currentcolor;
2998         float ambientscale = rtlight->ambientscale;
2999         float diffusescale = rtlight->diffusescale;
3000         float specularscale = rtlight->specularscale;
3001         // this is the location of the light in view space
3002         vec3_t viewlightorigin;
3003         // this transforms from view space (camera) to light space (cubemap)
3004         matrix4x4_t viewtolight;
3005         matrix4x4_t lighttoview;
3006         float viewtolight16f[16];
3007         // light source
3008         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3009         if (rtlight->currentcubemap != r_texture_whitecube)
3010                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3011         if (diffusescale > 0)
3012                 permutation |= SHADERPERMUTATION_DIFFUSE;
3013         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3014                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3015         if (r_shadow_usingshadowmap2d)
3016         {
3017                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3018                 if (r_shadow_shadowmapvsdct)
3019                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3020
3021                 if (r_shadow_shadowmap2ddepthbuffer)
3022                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3023         }
3024         if (vid.allowalphatocoverage)
3025                 GL_AlphaToCoverage(false);
3026         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3027         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3028         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3029         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3030         switch(vid.renderpath)
3031         {
3032         case RENDERPATH_D3D9:
3033 #ifdef SUPPORTD3D
3034                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3039                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3040                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3041                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3042                 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);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3045
3046                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3047                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3048                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3049                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3050                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3051 #endif
3052                 break;
3053         case RENDERPATH_D3D10:
3054                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055                 break;
3056         case RENDERPATH_D3D11:
3057                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3058                 break;
3059         case RENDERPATH_GL20:
3060         case RENDERPATH_GLES2:
3061                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3062                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3063                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3064                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3065                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3066                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3067                 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]);
3068                 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]);
3069                 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);
3070                 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]);
3071                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3072
3073                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3074                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3075                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3076                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3077                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3078                 break;
3079         case RENDERPATH_GL11:
3080         case RENDERPATH_GL13:
3081         case RENDERPATH_GLES1:
3082                 break;
3083         case RENDERPATH_SOFT:
3084                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3086                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3089                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3090                 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]);
3091                 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]);
3092                 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);
3093                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3094                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3095
3096                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3097                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3098                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3099                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3100                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3101                 break;
3102         }
3103 }
3104
3105 #define SKINFRAME_HASH 1024
3106
3107 typedef struct
3108 {
3109         unsigned int loadsequence; // incremented each level change
3110         memexpandablearray_t array;
3111         skinframe_t *hash[SKINFRAME_HASH];
3112 }
3113 r_skinframe_t;
3114 r_skinframe_t r_skinframe;
3115
3116 void R_SkinFrame_PrepareForPurge(void)
3117 {
3118         r_skinframe.loadsequence++;
3119         // wrap it without hitting zero
3120         if (r_skinframe.loadsequence >= 200)
3121                 r_skinframe.loadsequence = 1;
3122 }
3123
3124 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3125 {
3126         if (!skinframe)
3127                 return;
3128         // mark the skinframe as used for the purging code
3129         skinframe->loadsequence = r_skinframe.loadsequence;
3130 }
3131
3132 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3133 {
3134         if (s->merged == s->base)
3135                 s->merged = NULL;
3136         R_PurgeTexture(s->stain); s->stain = NULL;
3137         R_PurgeTexture(s->merged); s->merged = NULL;
3138         R_PurgeTexture(s->base); s->base = NULL;
3139         R_PurgeTexture(s->pants); s->pants = NULL;
3140         R_PurgeTexture(s->shirt); s->shirt = NULL;
3141         R_PurgeTexture(s->nmap); s->nmap = NULL;
3142         R_PurgeTexture(s->gloss); s->gloss = NULL;
3143         R_PurgeTexture(s->glow); s->glow = NULL;
3144         R_PurgeTexture(s->fog); s->fog = NULL;
3145         R_PurgeTexture(s->reflect); s->reflect = NULL;
3146         s->loadsequence = 0;
3147 }
3148
3149 void R_SkinFrame_Purge(void)
3150 {
3151         int i;
3152         skinframe_t *s;
3153         for (i = 0;i < SKINFRAME_HASH;i++)
3154         {
3155                 for (s = r_skinframe.hash[i];s;s = s->next)
3156                 {
3157                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3158                                 R_SkinFrame_PurgeSkinFrame(s);
3159                 }
3160         }
3161 }
3162
3163 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3164         skinframe_t *item;
3165         char basename[MAX_QPATH];
3166
3167         Image_StripImageExtension(name, basename, sizeof(basename));
3168
3169         if( last == NULL ) {
3170                 int hashindex;
3171                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3172                 item = r_skinframe.hash[hashindex];
3173         } else {
3174                 item = last->next;
3175         }
3176
3177         // linearly search through the hash bucket
3178         for( ; item ; item = item->next ) {
3179                 if( !strcmp( item->basename, basename ) ) {
3180                         return item;
3181                 }
3182         }
3183         return NULL;
3184 }
3185
3186 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3187 {
3188         skinframe_t *item;
3189         int hashindex;
3190         char basename[MAX_QPATH];
3191
3192         Image_StripImageExtension(name, basename, sizeof(basename));
3193
3194         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3195         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3196                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3197                         break;
3198
3199         if (!item) {
3200                 rtexture_t *dyntexture;
3201                 // check whether its a dynamic texture
3202                 dyntexture = CL_GetDynTexture( basename );
3203                 if (!add && !dyntexture)
3204                         return NULL;
3205                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3206                 memset(item, 0, sizeof(*item));
3207                 strlcpy(item->basename, basename, sizeof(item->basename));
3208                 item->base = dyntexture; // either NULL or dyntexture handle
3209                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3210                 item->comparewidth = comparewidth;
3211                 item->compareheight = compareheight;
3212                 item->comparecrc = comparecrc;
3213                 item->next = r_skinframe.hash[hashindex];
3214                 r_skinframe.hash[hashindex] = item;
3215         }
3216         else if (textureflags & TEXF_FORCE_RELOAD)
3217         {
3218                 rtexture_t *dyntexture;
3219                 // check whether its a dynamic texture
3220                 dyntexture = CL_GetDynTexture( basename );
3221                 if (!add && !dyntexture)
3222                         return NULL;
3223                 R_SkinFrame_PurgeSkinFrame(item);
3224         }
3225         else if( item->base == NULL )
3226         {
3227                 rtexture_t *dyntexture;
3228                 // check whether its a dynamic texture
3229                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3230                 dyntexture = CL_GetDynTexture( basename );
3231                 item->base = dyntexture; // either NULL or dyntexture handle
3232         }
3233
3234         R_SkinFrame_MarkUsed(item);
3235         return item;
3236 }
3237
3238 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3239         { \
3240                 unsigned long long avgcolor[5], wsum; \
3241                 int pix, comp, w; \
3242                 avgcolor[0] = 0; \
3243                 avgcolor[1] = 0; \
3244                 avgcolor[2] = 0; \
3245                 avgcolor[3] = 0; \
3246                 avgcolor[4] = 0; \
3247                 wsum = 0; \
3248                 for(pix = 0; pix < cnt; ++pix) \
3249                 { \
3250                         w = 0; \
3251                         for(comp = 0; comp < 3; ++comp) \
3252                                 w += getpixel; \
3253                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3254                         { \
3255                                 ++wsum; \
3256                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3257                                 w = getpixel; \
3258                                 for(comp = 0; comp < 3; ++comp) \
3259                                         avgcolor[comp] += getpixel * w; \
3260                                 avgcolor[3] += w; \
3261                         } \
3262                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3263                         avgcolor[4] += getpixel; \
3264                 } \
3265                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3266                         avgcolor[3] = 1; \
3267                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3271         }
3272
3273 extern cvar_t gl_picmip;
3274 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3275 {
3276         int j;
3277         unsigned char *pixels;
3278         unsigned char *bumppixels;
3279         unsigned char *basepixels = NULL;
3280         int basepixels_width = 0;
3281         int basepixels_height = 0;
3282         skinframe_t *skinframe;
3283         rtexture_t *ddsbase = NULL;
3284         qboolean ddshasalpha = false;
3285         float ddsavgcolor[4];
3286         char basename[MAX_QPATH];
3287         int miplevel = R_PicmipForFlags(textureflags);
3288         int savemiplevel = miplevel;
3289         int mymiplevel;
3290         char vabuf[1024];
3291
3292         if (cls.state == ca_dedicated)
3293                 return NULL;
3294
3295         // return an existing skinframe if already loaded
3296         // if loading of the first image fails, don't make a new skinframe as it
3297         // would cause all future lookups of this to be missing
3298         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3299         if (skinframe && skinframe->base)
3300                 return skinframe;
3301
3302         Image_StripImageExtension(name, basename, sizeof(basename));
3303
3304         // check for DDS texture file first
3305         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3306         {
3307                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3308                 if (basepixels == NULL)
3309                         return NULL;
3310         }
3311
3312         // FIXME handle miplevel
3313
3314         if (developer_loading.integer)
3315                 Con_Printf("loading skin \"%s\"\n", name);
3316
3317         // we've got some pixels to store, so really allocate this new texture now
3318         if (!skinframe)
3319                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3320         textureflags &= ~TEXF_FORCE_RELOAD;
3321         skinframe->stain = NULL;
3322         skinframe->merged = NULL;
3323         skinframe->base = NULL;
3324         skinframe->pants = NULL;
3325         skinframe->shirt = NULL;
3326         skinframe->nmap = NULL;
3327         skinframe->gloss = NULL;
3328         skinframe->glow = NULL;
3329         skinframe->fog = NULL;
3330         skinframe->reflect = NULL;
3331         skinframe->hasalpha = false;
3332         // we could store the q2animname here too
3333
3334         if (ddsbase)
3335         {
3336                 skinframe->base = ddsbase;
3337                 skinframe->hasalpha = ddshasalpha;
3338                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3339                 if (r_loadfog && skinframe->hasalpha)
3340                         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);
3341                 //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]);
3342         }
3343         else
3344         {
3345                 basepixels_width = image_width;
3346                 basepixels_height = image_height;
3347                 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);
3348                 if (textureflags & TEXF_ALPHA)
3349                 {
3350                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3351                         {
3352                                 if (basepixels[j] < 255)
3353                                 {
3354                                         skinframe->hasalpha = true;
3355                                         break;
3356                                 }
3357                         }
3358                         if (r_loadfog && skinframe->hasalpha)
3359                         {
3360                                 // has transparent pixels
3361                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3362                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3363                                 {
3364                                         pixels[j+0] = 255;
3365                                         pixels[j+1] = 255;
3366                                         pixels[j+2] = 255;
3367                                         pixels[j+3] = basepixels[j+3];
3368                                 }
3369                                 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);
3370                                 Mem_Free(pixels);
3371                         }
3372                 }
3373                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3374 #ifndef USE_GLES2
3375                 //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]);
3376                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3377                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3378                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3379                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3380 #endif
3381         }
3382
3383         if (r_loaddds)
3384         {
3385                 mymiplevel = savemiplevel;
3386                 if (r_loadnormalmap)
3387                         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);
3388                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3389                 if (r_loadgloss)
3390                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3391                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3392                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3393                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3394         }
3395
3396         // _norm is the name used by tenebrae and has been adopted as standard
3397         if (r_loadnormalmap && skinframe->nmap == NULL)
3398         {
3399                 mymiplevel = savemiplevel;
3400                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3401                 {
3402                         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);
3403                         Mem_Free(pixels);
3404                         pixels = NULL;
3405                 }
3406                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3407                 {
3408                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3409                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3410                         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);
3411                         Mem_Free(pixels);
3412                         Mem_Free(bumppixels);
3413                 }
3414                 else if (r_shadow_bumpscale_basetexture.value > 0)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3418                         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);
3419                         Mem_Free(pixels);
3420                 }
3421 #ifndef USE_GLES2
3422                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3423                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3424 #endif
3425         }
3426
3427         // _luma is supported only for tenebrae compatibility
3428         // _glow is the preferred name
3429         mymiplevel = savemiplevel;
3430         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))))
3431         {
3432                 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);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3435                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437                 Mem_Free(pixels);pixels = NULL;
3438         }
3439
3440         mymiplevel = savemiplevel;
3441         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3442         {
3443                 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);
3444 #ifndef USE_GLES2
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3446                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 #endif
3448                 Mem_Free(pixels);
3449                 pixels = NULL;
3450         }
3451
3452         mymiplevel = savemiplevel;
3453         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3454         {
3455                 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);
3456 #ifndef USE_GLES2
3457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3458                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3459 #endif
3460                 Mem_Free(pixels);
3461                 pixels = NULL;
3462         }
3463
3464         mymiplevel = savemiplevel;
3465         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3466         {
3467                 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);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3470                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3471 #endif
3472                 Mem_Free(pixels);
3473                 pixels = NULL;
3474         }
3475
3476         mymiplevel = savemiplevel;
3477         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3478         {
3479                 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);
3480 #ifndef USE_GLES2
3481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3482                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3483 #endif
3484                 Mem_Free(pixels);
3485                 pixels = NULL;
3486         }
3487
3488         if (basepixels)
3489                 Mem_Free(basepixels);
3490
3491         return skinframe;
3492 }
3493
3494 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3495 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3496 {
3497         int i;
3498         skinframe_t *skinframe;
3499         char vabuf[1024];
3500
3501         if (cls.state == ca_dedicated)
3502                 return NULL;
3503
3504         // if already loaded just return it, otherwise make a new skinframe
3505         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3506         if (skinframe->base)
3507                 return skinframe;
3508         textureflags &= ~TEXF_FORCE_RELOAD;
3509
3510         skinframe->stain = NULL;
3511         skinframe->merged = NULL;
3512         skinframe->base = NULL;
3513         skinframe->pants = NULL;
3514         skinframe->shirt = NULL;
3515         skinframe->nmap = NULL;
3516         skinframe->gloss = NULL;
3517         skinframe->glow = NULL;
3518         skinframe->fog = NULL;
3519         skinframe->reflect = NULL;
3520         skinframe->hasalpha = false;
3521
3522         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3523         if (!skindata)
3524                 return NULL;
3525
3526         if (developer_loading.integer)
3527                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3528
3529         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3530         {
3531                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3532                 unsigned char *b = a + width * height * 4;
3533                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3534                 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);
3535                 Mem_Free(a);
3536         }
3537         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3538         if (textureflags & TEXF_ALPHA)
3539         {
3540                 for (i = 3;i < width * height * 4;i += 4)
3541                 {
3542                         if (skindata[i] < 255)
3543                         {
3544                                 skinframe->hasalpha = true;
3545                                 break;
3546                         }
3547                 }
3548                 if (r_loadfog && skinframe->hasalpha)
3549                 {
3550                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3551                         memcpy(fogpixels, skindata, width * height * 4);
3552                         for (i = 0;i < width * height * 4;i += 4)
3553                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3554                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3555                         Mem_Free(fogpixels);
3556                 }
3557         }
3558
3559         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3560         //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]);
3561
3562         return skinframe;
3563 }
3564
3565 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3566 {
3567         int i;
3568         int featuresmask;
3569         skinframe_t *skinframe;
3570
3571         if (cls.state == ca_dedicated)
3572                 return NULL;
3573
3574         // if already loaded just return it, otherwise make a new skinframe
3575         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3576         if (skinframe->base)
3577                 return skinframe;
3578         //textureflags &= ~TEXF_FORCE_RELOAD;
3579
3580         skinframe->stain = NULL;
3581         skinframe->merged = NULL;
3582         skinframe->base = NULL;
3583         skinframe->pants = NULL;
3584         skinframe->shirt = NULL;
3585         skinframe->nmap = NULL;
3586         skinframe->gloss = NULL;
3587         skinframe->glow = NULL;
3588         skinframe->fog = NULL;
3589         skinframe->reflect = NULL;
3590         skinframe->hasalpha = false;
3591
3592         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3593         if (!skindata)
3594                 return NULL;
3595
3596         if (developer_loading.integer)
3597                 Con_Printf("loading quake skin \"%s\"\n", name);
3598
3599         // 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)
3600         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3601         memcpy(skinframe->qpixels, skindata, width*height);
3602         skinframe->qwidth = width;
3603         skinframe->qheight = height;
3604
3605         featuresmask = 0;
3606         for (i = 0;i < width * height;i++)
3607                 featuresmask |= palette_featureflags[skindata[i]];
3608
3609         skinframe->hasalpha = false;
3610         // fence textures
3611         if (name[0] == '{')
3612                 skinframe->hasalpha = true;
3613         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3614         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3615         skinframe->qgeneratemerged = true;
3616         skinframe->qgeneratebase = skinframe->qhascolormapping;
3617         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3618
3619         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3620         //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]);
3621
3622         return skinframe;
3623 }
3624
3625 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3626 {
3627         int width;
3628         int height;
3629         unsigned char *skindata;
3630         char vabuf[1024];
3631
3632         if (!skinframe->qpixels)
3633                 return;
3634
3635         if (!skinframe->qhascolormapping)
3636                 colormapped = false;
3637
3638         if (colormapped)
3639         {
3640                 if (!skinframe->qgeneratebase)
3641                         return;
3642         }
3643         else
3644         {
3645                 if (!skinframe->qgeneratemerged)
3646                         return;
3647         }
3648
3649         width = skinframe->qwidth;
3650         height = skinframe->qheight;
3651         skindata = skinframe->qpixels;
3652
3653         if (skinframe->qgeneratenmap)
3654         {
3655                 unsigned char *a, *b;
3656                 skinframe->qgeneratenmap = false;
3657                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3658                 b = a + width * height * 4;
3659                 // use either a custom palette or the quake palette
3660                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3661                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3662                 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);
3663                 Mem_Free(a);
3664         }
3665
3666         if (skinframe->qgenerateglow)
3667         {
3668                 skinframe->qgenerateglow = false;
3669                 if (skinframe->hasalpha) // fence textures
3670                         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
3671                 else
3672                         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
3673         }
3674
3675         if (colormapped)
3676         {
3677                 skinframe->qgeneratebase = false;
3678                 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);
3679                 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);
3680                 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);
3681         }
3682         else
3683         {
3684                 skinframe->qgeneratemerged = false;
3685                 if (skinframe->hasalpha) // fence textures
3686                         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);
3687                 else
3688                         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);
3689         }
3690
3691         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3692         {
3693                 Mem_Free(skinframe->qpixels);
3694                 skinframe->qpixels = NULL;
3695         }
3696 }
3697
3698 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)
3699 {
3700         int i;
3701         skinframe_t *skinframe;
3702         char vabuf[1024];
3703
3704         if (cls.state == ca_dedicated)
3705                 return NULL;
3706
3707         // if already loaded just return it, otherwise make a new skinframe
3708         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3709         if (skinframe->base)
3710                 return skinframe;
3711         textureflags &= ~TEXF_FORCE_RELOAD;
3712
3713         skinframe->stain = NULL;
3714         skinframe->merged = NULL;
3715         skinframe->base = NULL;
3716         skinframe->pants = NULL;
3717         skinframe->shirt = NULL;
3718         skinframe->nmap = NULL;
3719         skinframe->gloss = NULL;
3720         skinframe->glow = NULL;
3721         skinframe->fog = NULL;
3722         skinframe->reflect = NULL;
3723         skinframe->hasalpha = false;
3724
3725         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3726         if (!skindata)
3727                 return NULL;
3728
3729         if (developer_loading.integer)
3730                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3731
3732         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3733         if (textureflags & TEXF_ALPHA)
3734         {
3735                 for (i = 0;i < width * height;i++)
3736                 {
3737                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3738                         {
3739                                 skinframe->hasalpha = true;
3740                                 break;
3741                         }
3742                 }
3743                 if (r_loadfog && skinframe->hasalpha)
3744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3745         }
3746
3747         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3748         //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]);
3749
3750         return skinframe;
3751 }
3752
3753 skinframe_t *R_SkinFrame_LoadMissing(void)
3754 {
3755         skinframe_t *skinframe;
3756
3757         if (cls.state == ca_dedicated)
3758                 return NULL;
3759
3760         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3761         skinframe->stain = NULL;
3762         skinframe->merged = NULL;
3763         skinframe->base = NULL;
3764         skinframe->pants = NULL;
3765         skinframe->shirt = NULL;
3766         skinframe->nmap = NULL;
3767         skinframe->gloss = NULL;
3768         skinframe->glow = NULL;
3769         skinframe->fog = NULL;
3770         skinframe->reflect = NULL;
3771         skinframe->hasalpha = false;
3772
3773         skinframe->avgcolor[0] = rand() / RAND_MAX;
3774         skinframe->avgcolor[1] = rand() / RAND_MAX;
3775         skinframe->avgcolor[2] = rand() / RAND_MAX;
3776         skinframe->avgcolor[3] = 1;
3777
3778         return skinframe;
3779 }
3780
3781 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3782 typedef struct suffixinfo_s
3783 {
3784         const char *suffix;
3785         qboolean flipx, flipy, flipdiagonal;
3786 }
3787 suffixinfo_t;
3788 static suffixinfo_t suffix[3][6] =
3789 {
3790         {
3791                 {"px",   false, false, false},
3792                 {"nx",   false, false, false},
3793                 {"py",   false, false, false},
3794                 {"ny",   false, false, false},
3795                 {"pz",   false, false, false},
3796                 {"nz",   false, false, false}
3797         },
3798         {
3799                 {"posx", false, false, false},
3800                 {"negx", false, false, false},
3801                 {"posy", false, false, false},
3802                 {"negy", false, false, false},
3803                 {"posz", false, false, false},
3804                 {"negz", false, false, false}
3805         },
3806         {
3807                 {"rt",    true, false,  true},
3808                 {"lf",   false,  true,  true},
3809                 {"ft",    true,  true, false},
3810                 {"bk",   false, false, false},
3811                 {"up",    true, false,  true},
3812                 {"dn",    true, false,  true}
3813         }
3814 };
3815
3816 static int componentorder[4] = {0, 1, 2, 3};
3817
3818 static rtexture_t *R_LoadCubemap(const char *basename)
3819 {
3820         int i, j, cubemapsize;
3821         unsigned char *cubemappixels, *image_buffer;
3822         rtexture_t *cubemaptexture;
3823         char name[256];
3824         // must start 0 so the first loadimagepixels has no requested width/height
3825         cubemapsize = 0;
3826         cubemappixels = NULL;
3827         cubemaptexture = NULL;
3828         // keep trying different suffix groups (posx, px, rt) until one loads
3829         for (j = 0;j < 3 && !cubemappixels;j++)
3830         {
3831                 // load the 6 images in the suffix group
3832                 for (i = 0;i < 6;i++)
3833                 {
3834                         // generate an image name based on the base and and suffix
3835                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3836                         // load it
3837                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3838                         {
3839                                 // an image loaded, make sure width and height are equal
3840                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3841                                 {
3842                                         // if this is the first image to load successfully, allocate the cubemap memory
3843                                         if (!cubemappixels && image_width >= 1)
3844                                         {
3845                                                 cubemapsize = image_width;
3846                                                 // note this clears to black, so unavailable sides are black
3847                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3848                                         }
3849                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3850                                         if (cubemappixels)
3851                                                 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);
3852                                 }
3853                                 else
3854                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3855                                 // free the image
3856                                 Mem_Free(image_buffer);
3857                         }
3858                 }
3859         }
3860         // if a cubemap loaded, upload it
3861         if (cubemappixels)
3862         {
3863                 if (developer_loading.integer)
3864                         Con_Printf("loading cubemap \"%s\"\n", basename);
3865
3866                 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);
3867                 Mem_Free(cubemappixels);
3868         }
3869         else
3870         {
3871                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3872                 if (developer_loading.integer)
3873                 {
3874                         Con_Printf("(tried tried images ");
3875                         for (j = 0;j < 3;j++)
3876                                 for (i = 0;i < 6;i++)
3877                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3878                         Con_Print(" and was unable to find any of them).\n");
3879                 }
3880         }
3881         return cubemaptexture;
3882 }
3883
3884 rtexture_t *R_GetCubemap(const char *basename)
3885 {
3886         int i;
3887         for (i = 0;i < r_texture_numcubemaps;i++)
3888                 if (r_texture_cubemaps[i] != NULL)
3889                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3890                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3891         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3892                 return r_texture_whitecube;
3893         r_texture_numcubemaps++;
3894         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3895         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3896         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3897         return r_texture_cubemaps[i]->texture;
3898 }
3899
3900 static void R_Main_FreeViewCache(void)
3901 {
3902         if (r_refdef.viewcache.entityvisible)
3903                 Mem_Free(r_refdef.viewcache.entityvisible);
3904         if (r_refdef.viewcache.world_pvsbits)
3905                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3906         if (r_refdef.viewcache.world_leafvisible)
3907                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908         if (r_refdef.viewcache.world_surfacevisible)
3909                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3910         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3911 }
3912
3913 static void R_Main_ResizeViewCache(void)
3914 {
3915         int numentities = r_refdef.scene.numentities;
3916         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3917         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3918         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3919         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3920         if (r_refdef.viewcache.maxentities < numentities)
3921         {
3922                 r_refdef.viewcache.maxentities = numentities;
3923                 if (r_refdef.viewcache.entityvisible)
3924                         Mem_Free(r_refdef.viewcache.entityvisible);
3925                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3926         }
3927         if (r_refdef.viewcache.world_numclusters != numclusters)
3928         {
3929                 r_refdef.viewcache.world_numclusters = numclusters;
3930                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3931                 if (r_refdef.viewcache.world_pvsbits)
3932                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3933                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3934         }
3935         if (r_refdef.viewcache.world_numleafs != numleafs)
3936         {
3937                 r_refdef.viewcache.world_numleafs = numleafs;
3938                 if (r_refdef.viewcache.world_leafvisible)
3939                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3940                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3941         }
3942         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3943         {
3944                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3945                 if (r_refdef.viewcache.world_surfacevisible)
3946                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3947                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3948         }
3949 }
3950
3951 extern rtexture_t *loadingscreentexture;
3952 static void gl_main_start(void)
3953 {
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965         r_uniformbufferalignment = 32;
3966
3967         r_loaddds = r_texture_dds_load.integer != 0;
3968         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3969
3970         switch(vid.renderpath)
3971         {
3972         case RENDERPATH_GL20:
3973         case RENDERPATH_D3D9:
3974         case RENDERPATH_D3D10:
3975         case RENDERPATH_D3D11:
3976         case RENDERPATH_SOFT:
3977         case RENDERPATH_GLES2:
3978                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3979                 Cvar_SetValueQuick(&gl_combine, 1);
3980                 Cvar_SetValueQuick(&r_glsl, 1);
3981                 r_loadnormalmap = true;
3982                 r_loadgloss = true;
3983                 r_loadfog = false;
3984 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3985                 if (vid.support.arb_uniform_buffer_object)
3986                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3987 #endif
3988                         break;
3989         case RENDERPATH_GL13:
3990         case RENDERPATH_GLES1:
3991                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3992                 Cvar_SetValueQuick(&gl_combine, 1);
3993                 Cvar_SetValueQuick(&r_glsl, 0);
3994                 r_loadnormalmap = false;
3995                 r_loadgloss = false;
3996                 r_loadfog = true;
3997                 break;
3998         case RENDERPATH_GL11:
3999                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000                 Cvar_SetValueQuick(&gl_combine, 0);
4001                 Cvar_SetValueQuick(&r_glsl, 0);
4002                 r_loadnormalmap = false;
4003                 r_loadgloss = false;
4004                 r_loadfog = true;
4005                 break;
4006         }
4007
4008         R_AnimCache_Free();
4009         R_FrameData_Reset();
4010         R_BufferData_Reset();
4011
4012         r_numqueries = 0;
4013         r_maxqueries = 0;
4014         memset(r_queries, 0, sizeof(r_queries));
4015
4016         r_qwskincache = NULL;
4017         r_qwskincache_size = 0;
4018
4019         // due to caching of texture_t references, the collision cache must be reset
4020         Collision_Cache_Reset(true);
4021
4022         // set up r_skinframe loading system for textures
4023         memset(&r_skinframe, 0, sizeof(r_skinframe));
4024         r_skinframe.loadsequence = 1;
4025         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4026
4027         r_main_texturepool = R_AllocTexturePool();
4028         R_BuildBlankTextures();
4029         R_BuildNoTexture();
4030         if (vid.support.arb_texture_cube_map)
4031         {
4032                 R_BuildWhiteCube();
4033                 R_BuildNormalizationCube();
4034         }
4035         r_texture_fogattenuation = NULL;
4036         r_texture_fogheighttexture = NULL;
4037         r_texture_gammaramps = NULL;
4038         //r_texture_fogintensity = NULL;
4039         memset(&r_fb, 0, sizeof(r_fb));
4040         r_glsl_permutation = NULL;
4041         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4042         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4043 #ifdef SUPPORTD3D
4044         r_hlsl_permutation = NULL;
4045         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4046         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4047 #endif
4048         memset(&r_svbsp, 0, sizeof (r_svbsp));
4049
4050         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4051         r_texture_numcubemaps = 0;
4052
4053         r_refdef.fogmasktable_density = 0;
4054
4055 #ifdef __ANDROID__
4056         // For Steelstorm Android
4057         // FIXME CACHE the program and reload
4058         // FIXME see possible combinations for SS:BR android
4059         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4060         R_SetupShader_SetPermutationGLSL(0, 12);
4061         R_SetupShader_SetPermutationGLSL(0, 13);
4062         R_SetupShader_SetPermutationGLSL(0, 8388621);
4063         R_SetupShader_SetPermutationGLSL(3, 0);
4064         R_SetupShader_SetPermutationGLSL(3, 2048);
4065         R_SetupShader_SetPermutationGLSL(5, 0);
4066         R_SetupShader_SetPermutationGLSL(5, 2);
4067         R_SetupShader_SetPermutationGLSL(5, 2048);
4068         R_SetupShader_SetPermutationGLSL(5, 8388608);
4069         R_SetupShader_SetPermutationGLSL(11, 1);
4070         R_SetupShader_SetPermutationGLSL(11, 2049);
4071         R_SetupShader_SetPermutationGLSL(11, 8193);
4072         R_SetupShader_SetPermutationGLSL(11, 10241);
4073         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4074 #endif
4075 }
4076
4077 static void gl_main_shutdown(void)
4078 {
4079         R_AnimCache_Free();
4080         R_FrameData_Reset();
4081         R_BufferData_Reset();
4082
4083         R_Main_FreeViewCache();
4084
4085         switch(vid.renderpath)
4086         {
4087         case RENDERPATH_GL11:
4088         case RENDERPATH_GL13:
4089         case RENDERPATH_GL20:
4090         case RENDERPATH_GLES1:
4091         case RENDERPATH_GLES2:
4092 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4093                 if (r_maxqueries)
4094                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4095 #endif
4096                 break;
4097         case RENDERPATH_D3D9:
4098                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4099                 break;
4100         case RENDERPATH_D3D10:
4101                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4102                 break;
4103         case RENDERPATH_D3D11:
4104                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4105                 break;
4106         case RENDERPATH_SOFT:
4107                 break;
4108         }
4109
4110         r_numqueries = 0;
4111         r_maxqueries = 0;
4112         memset(r_queries, 0, sizeof(r_queries));
4113
4114         r_qwskincache = NULL;
4115         r_qwskincache_size = 0;
4116
4117         // clear out the r_skinframe state
4118         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4119         memset(&r_skinframe, 0, sizeof(r_skinframe));
4120
4121         if (r_svbsp.nodes)
4122                 Mem_Free(r_svbsp.nodes);
4123         memset(&r_svbsp, 0, sizeof (r_svbsp));
4124         R_FreeTexturePool(&r_main_texturepool);
4125         loadingscreentexture = NULL;
4126         r_texture_blanknormalmap = NULL;
4127         r_texture_white = NULL;
4128         r_texture_grey128 = NULL;
4129         r_texture_black = NULL;
4130         r_texture_whitecube = NULL;
4131         r_texture_normalizationcube = NULL;
4132         r_texture_fogattenuation = NULL;
4133         r_texture_fogheighttexture = NULL;
4134         r_texture_gammaramps = NULL;
4135         r_texture_numcubemaps = 0;
4136         //r_texture_fogintensity = NULL;
4137         memset(&r_fb, 0, sizeof(r_fb));
4138         R_GLSL_Restart_f();
4139
4140         r_glsl_permutation = NULL;
4141         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4142         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4143 #ifdef SUPPORTD3D
4144         r_hlsl_permutation = NULL;
4145         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4146         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4147 #endif
4148 }
4149
4150 static void gl_main_newmap(void)
4151 {
4152         // FIXME: move this code to client
4153         char *entities, entname[MAX_QPATH];
4154         if (r_qwskincache)
4155                 Mem_Free(r_qwskincache);
4156         r_qwskincache = NULL;
4157         r_qwskincache_size = 0;
4158         if (cl.worldmodel)
4159         {
4160                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4161                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4162                 {
4163                         CL_ParseEntityLump(entities);
4164                         Mem_Free(entities);
4165                         return;
4166                 }
4167                 if (cl.worldmodel->brush.entities)
4168                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4169         }
4170         R_Main_FreeViewCache();
4171
4172         R_FrameData_Reset();
4173         R_BufferData_Reset();
4174 }
4175
4176 void GL_Main_Init(void)
4177 {
4178         int i;
4179         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4180         R_InitShaderModeInfo();
4181
4182         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4183         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4184         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4185         if (gamemode == GAME_NEHAHRA)
4186         {
4187                 Cvar_RegisterVariable (&gl_fogenable);
4188                 Cvar_RegisterVariable (&gl_fogdensity);
4189                 Cvar_RegisterVariable (&gl_fogred);
4190                 Cvar_RegisterVariable (&gl_foggreen);
4191                 Cvar_RegisterVariable (&gl_fogblue);
4192                 Cvar_RegisterVariable (&gl_fogstart);
4193                 Cvar_RegisterVariable (&gl_fogend);
4194                 Cvar_RegisterVariable (&gl_skyclip);
4195         }
4196         Cvar_RegisterVariable(&r_motionblur);
4197         Cvar_RegisterVariable(&r_damageblur);
4198         Cvar_RegisterVariable(&r_motionblur_averaging);
4199         Cvar_RegisterVariable(&r_motionblur_randomize);
4200         Cvar_RegisterVariable(&r_motionblur_minblur);
4201         Cvar_RegisterVariable(&r_motionblur_maxblur);
4202         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4203         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4204         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4205         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4206         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4207         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4208         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4209         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4210         Cvar_RegisterVariable(&r_equalize_entities_by);
4211         Cvar_RegisterVariable(&r_equalize_entities_to);
4212         Cvar_RegisterVariable(&r_depthfirst);
4213         Cvar_RegisterVariable(&r_useinfinitefarclip);
4214         Cvar_RegisterVariable(&r_farclip_base);
4215         Cvar_RegisterVariable(&r_farclip_world);
4216         Cvar_RegisterVariable(&r_nearclip);
4217         Cvar_RegisterVariable(&r_deformvertexes);
4218         Cvar_RegisterVariable(&r_transparent);
4219         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4220         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4221         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4222         Cvar_RegisterVariable(&r_showoverdraw);
4223         Cvar_RegisterVariable(&r_showbboxes);
4224         Cvar_RegisterVariable(&r_showbboxes_client);
4225         Cvar_RegisterVariable(&r_showsurfaces);
4226         Cvar_RegisterVariable(&r_showtris);
4227         Cvar_RegisterVariable(&r_shownormals);
4228         Cvar_RegisterVariable(&r_showlighting);
4229         Cvar_RegisterVariable(&r_showshadowvolumes);
4230         Cvar_RegisterVariable(&r_showcollisionbrushes);
4231         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4232         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4233         Cvar_RegisterVariable(&r_showdisabledepthtest);
4234         Cvar_RegisterVariable(&r_drawportals);
4235         Cvar_RegisterVariable(&r_drawentities);
4236         Cvar_RegisterVariable(&r_draw2d);
4237         Cvar_RegisterVariable(&r_drawworld);
4238         Cvar_RegisterVariable(&r_cullentities_trace);
4239         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4240         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4241         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4242         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4243         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4244         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4245         Cvar_RegisterVariable(&r_sortentities);
4246         Cvar_RegisterVariable(&r_drawviewmodel);
4247         Cvar_RegisterVariable(&r_drawexteriormodel);
4248         Cvar_RegisterVariable(&r_speeds);
4249         Cvar_RegisterVariable(&r_fullbrights);
4250         Cvar_RegisterVariable(&r_wateralpha);
4251         Cvar_RegisterVariable(&r_dynamic);
4252         Cvar_RegisterVariable(&r_fakelight);
4253         Cvar_RegisterVariable(&r_fakelight_intensity);
4254         Cvar_RegisterVariable(&r_fullbright_directed);
4255         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4256         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4257         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4258         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4259         Cvar_RegisterVariable(&r_fullbright);
4260         Cvar_RegisterVariable(&r_shadows);
4261         Cvar_RegisterVariable(&r_shadows_darken);
4262         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4263         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4264         Cvar_RegisterVariable(&r_shadows_throwdistance);
4265         Cvar_RegisterVariable(&r_shadows_throwdirection);
4266         Cvar_RegisterVariable(&r_shadows_focus);
4267         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4268         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4269         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4270         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4271         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4272         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4273         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4274         Cvar_RegisterVariable(&r_fog_exp2);
4275         Cvar_RegisterVariable(&r_fog_clear);
4276         Cvar_RegisterVariable(&r_drawfog);
4277         Cvar_RegisterVariable(&r_transparentdepthmasking);
4278         Cvar_RegisterVariable(&r_transparent_sortmindist);
4279         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4280         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4281         Cvar_RegisterVariable(&r_texture_dds_load);
4282         Cvar_RegisterVariable(&r_texture_dds_save);
4283         Cvar_RegisterVariable(&r_textureunits);
4284         Cvar_RegisterVariable(&gl_combine);
4285         Cvar_RegisterVariable(&r_usedepthtextures);
4286         Cvar_RegisterVariable(&r_viewfbo);
4287         Cvar_RegisterVariable(&r_viewscale);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4293         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4294         Cvar_RegisterVariable(&r_glsl);
4295         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4302         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4303         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4304         Cvar_RegisterVariable(&r_glsl_postprocess);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4312         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4313         Cvar_RegisterVariable(&r_celshading);
4314         Cvar_RegisterVariable(&r_celoutlines);
4315
4316         Cvar_RegisterVariable(&r_water);
4317         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4318         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4319         Cvar_RegisterVariable(&r_water_clippingplanebias);
4320         Cvar_RegisterVariable(&r_water_refractdistort);
4321         Cvar_RegisterVariable(&r_water_reflectdistort);
4322         Cvar_RegisterVariable(&r_water_scissormode);
4323         Cvar_RegisterVariable(&r_water_lowquality);
4324         Cvar_RegisterVariable(&r_water_hideplayer);
4325         Cvar_RegisterVariable(&r_water_fbo);
4326
4327         Cvar_RegisterVariable(&r_lerpsprites);
4328         Cvar_RegisterVariable(&r_lerpmodels);
4329         Cvar_RegisterVariable(&r_lerplightstyles);
4330         Cvar_RegisterVariable(&r_waterscroll);
4331         Cvar_RegisterVariable(&r_bloom);
4332         Cvar_RegisterVariable(&r_bloom_colorscale);
4333         Cvar_RegisterVariable(&r_bloom_brighten);
4334         Cvar_RegisterVariable(&r_bloom_blur);
4335         Cvar_RegisterVariable(&r_bloom_resolution);
4336         Cvar_RegisterVariable(&r_bloom_colorexponent);
4337         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4338         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4339         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4340         Cvar_RegisterVariable(&r_hdr_glowintensity);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4346         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4347         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4348         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4349         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4350         Cvar_RegisterVariable(&developer_texturelogging);
4351         Cvar_RegisterVariable(&gl_lightmaps);
4352         Cvar_RegisterVariable(&r_test);
4353         Cvar_RegisterVariable(&r_batch_multidraw);
4354         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4355         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4356         Cvar_RegisterVariable(&r_glsl_skeletal);
4357         Cvar_RegisterVariable(&r_glsl_saturation);
4358         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4359         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4360         Cvar_RegisterVariable(&r_framedatasize);
4361         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4362                 Cvar_RegisterVariable(&r_buffermegs[i]);
4363         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4364         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4365                 Cvar_SetValue("r_fullbrights", 0);
4366 #ifdef DP_MOBILETOUCH
4367         // GLES devices have terrible depth precision in general, so...
4368         Cvar_SetValueQuick(&r_nearclip, 4);
4369         Cvar_SetValueQuick(&r_farclip_base, 4096);
4370         Cvar_SetValueQuick(&r_farclip_world, 0);
4371         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4372 #endif
4373         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4374 }
4375
4376 void Render_Init(void)
4377 {
4378         gl_backend_init();
4379         R_Textures_Init();
4380         GL_Main_Init();
4381         Font_Init();
4382         GL_Draw_Init();
4383         R_Shadow_Init();
4384         R_Sky_Init();
4385         GL_Surf_Init();
4386         Sbar_Init();
4387         R_Particles_Init();
4388         R_Explosion_Init();
4389         R_LightningBeams_Init();
4390         Mod_RenderInit();
4391 }
4392
4393 /*
4394 ===============
4395 GL_Init
4396 ===============
4397 */
4398 #ifndef USE_GLES2
4399 extern char *ENGINE_EXTENSIONS;
4400 void GL_Init (void)
4401 {
4402         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4403         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4404         gl_version = (const char *)qglGetString(GL_VERSION);
4405         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4406
4407         if (!gl_extensions)
4408                 gl_extensions = "";
4409         if (!gl_platformextensions)
4410                 gl_platformextensions = "";
4411
4412         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4413         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4414         Con_Printf("GL_VERSION: %s\n", gl_version);
4415         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4416         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4417
4418         VID_CheckExtensions();
4419
4420         // LordHavoc: report supported extensions
4421 #ifdef CONFIG_MENU
4422         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4423 #else
4424         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4425 #endif
4426
4427         // clear to black (loading plaque will be seen over this)
4428         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4429 }
4430 #endif
4431
4432 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4433 {
4434         int i;
4435         mplane_t *p;
4436         if (r_trippy.integer)
4437                 return false;
4438         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4439         {
4440                 p = r_refdef.view.frustum + i;
4441                 switch(p->signbits)
4442                 {
4443                 default:
4444                 case 0:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 1:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 2:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 3:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 4:
4461                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 5:
4465                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 6:
4469                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 7:
4473                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 }
4477         }
4478         return false;
4479 }
4480
4481 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4482 {
4483         int i;
4484         const mplane_t *p;
4485         if (r_trippy.integer)
4486                 return false;
4487         for (i = 0;i < numplanes;i++)
4488         {
4489                 p = planes + i;
4490                 switch(p->signbits)
4491                 {
4492                 default:
4493                 case 0:
4494                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4495                                 return true;
4496                         break;
4497                 case 1:
4498                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499                                 return true;
4500                         break;
4501                 case 2:
4502                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 3:
4506                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 4:
4510                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 5:
4514                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 6:
4518                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 7:
4522                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 }
4526         }
4527         return false;
4528 }
4529
4530 //==================================================================================
4531
4532 // LordHavoc: this stores temporary data used within the same frame
4533
4534 typedef struct r_framedata_mem_s
4535 {
4536         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4537         size_t size; // how much usable space
4538         size_t current; // how much space in use
4539         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4540         size_t wantedsize; // how much space was allocated
4541         unsigned char *data; // start of real data (16byte aligned)
4542 }
4543 r_framedata_mem_t;
4544
4545 static r_framedata_mem_t *r_framedata_mem;
4546
4547 void R_FrameData_Reset(void)
4548 {
4549         while (r_framedata_mem)
4550         {
4551                 r_framedata_mem_t *next = r_framedata_mem->purge;
4552                 Mem_Free(r_framedata_mem);
4553                 r_framedata_mem = next;
4554         }
4555 }
4556
4557 static void R_FrameData_Resize(qboolean mustgrow)
4558 {
4559         size_t wantedsize;
4560         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4561         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4562         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4563         {
4564                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4565                 newmem->wantedsize = wantedsize;
4566                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4567                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4568                 newmem->current = 0;
4569                 newmem->mark = 0;
4570                 newmem->purge = r_framedata_mem;
4571                 r_framedata_mem = newmem;
4572         }
4573 }
4574
4575 void R_FrameData_NewFrame(void)
4576 {
4577         R_FrameData_Resize(false);
4578         if (!r_framedata_mem)
4579                 return;
4580         // if we ran out of space on the last frame, free the old memory now
4581         while (r_framedata_mem->purge)
4582         {
4583                 // repeatedly remove the second item in the list, leaving only head
4584                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4585                 Mem_Free(r_framedata_mem->purge);
4586                 r_framedata_mem->purge = next;
4587         }
4588         // reset the current mem pointer
4589         r_framedata_mem->current = 0;
4590         r_framedata_mem->mark = 0;
4591 }
4592
4593 void *R_FrameData_Alloc(size_t size)
4594 {
4595         void *data;
4596         float newvalue;
4597
4598         // align to 16 byte boundary - the data pointer is already aligned, so we
4599         // only need to ensure the size of every allocation is also aligned
4600         size = (size + 15) & ~15;
4601
4602         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4603         {
4604                 // emergency - we ran out of space, allocate more memory
4605                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4606                 newvalue = r_framedatasize.value * 2.0f;
4607                 // 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
4608                 if (sizeof(size_t) >= 8)
4609                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4610                 else
4611                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4612                 // this might not be a growing it, but we'll allocate another buffer every time
4613                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4614                 R_FrameData_Resize(true);
4615         }
4616
4617         data = r_framedata_mem->data + r_framedata_mem->current;
4618         r_framedata_mem->current += size;
4619
4620         // count the usage for stats
4621         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4622         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4623
4624         return (void *)data;
4625 }
4626
4627 void *R_FrameData_Store(size_t size, void *data)
4628 {
4629         void *d = R_FrameData_Alloc(size);
4630         if (d && data)
4631                 memcpy(d, data, size);
4632         return d;
4633 }
4634
4635 void R_FrameData_SetMark(void)
4636 {
4637         if (!r_framedata_mem)
4638                 return;
4639         r_framedata_mem->mark = r_framedata_mem->current;
4640 }
4641
4642 void R_FrameData_ReturnToMark(void)
4643 {
4644         if (!r_framedata_mem)
4645                 return;
4646         r_framedata_mem->current = r_framedata_mem->mark;
4647 }
4648
4649 //==================================================================================
4650
4651 // avoid reusing the same buffer objects on consecutive frames
4652 #define R_BUFFERDATA_CYCLE 3
4653
4654 typedef struct r_bufferdata_buffer_s
4655 {
4656         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4657         size_t size; // how much usable space
4658         size_t current; // how much space in use
4659         r_meshbuffer_t *buffer; // the buffer itself
4660 }
4661 r_bufferdata_buffer_t;
4662
4663 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4664 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4665
4666 /// frees all dynamic buffers
4667 void R_BufferData_Reset(void)
4668 {
4669         int cycle, type;
4670         r_bufferdata_buffer_t **p, *mem;
4671         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4672         {
4673                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4674                 {
4675                         // free all buffers
4676                         p = &r_bufferdata_buffer[cycle][type];
4677                         while (*p)
4678                         {
4679                                 mem = *p;
4680                                 *p = (*p)->purge;
4681                                 if (mem->buffer)
4682                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4683                                 Mem_Free(mem);
4684                         }
4685                 }
4686         }
4687 }
4688
4689 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4690 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4691 {
4692         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4693         size_t size;
4694         float newvalue = r_buffermegs[type].value;
4695
4696         // increase the cvar if we have to (but only if we already have a mem)
4697         if (mustgrow && mem)
4698                 newvalue *= 2.0f;
4699         newvalue = bound(0.25f, newvalue, 256.0f);
4700         while (newvalue * 1024*1024 < minsize)
4701                 newvalue *= 2.0f;
4702
4703         // clamp the cvar to valid range
4704         newvalue = bound(0.25f, newvalue, 256.0f);
4705         if (r_buffermegs[type].value != newvalue)
4706                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4707
4708         // calculate size in bytes
4709         size = (size_t)(newvalue * 1024*1024);
4710         size = bound(131072, size, 256*1024*1024);
4711
4712         // allocate a new buffer if the size is different (purge old one later)
4713         // or if we were told we must grow the buffer
4714         if (!mem || mem->size != size || mustgrow)
4715         {
4716                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4717                 mem->size = size;
4718                 mem->current = 0;
4719                 if (type == R_BUFFERDATA_VERTEX)
4720                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4721                 else if (type == R_BUFFERDATA_INDEX16)
4722                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4723                 else if (type == R_BUFFERDATA_INDEX32)
4724                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4725                 else if (type == R_BUFFERDATA_UNIFORM)
4726                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4727                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4728                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4729         }
4730 }
4731
4732 void R_BufferData_NewFrame(void)
4733 {
4734         int type;
4735         r_bufferdata_buffer_t **p, *mem;
4736         // cycle to the next frame's buffers
4737         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4738         // if we ran out of space on the last time we used these buffers, free the old memory now
4739         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4740         {
4741                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4742                 {
4743                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4744                         // free all but the head buffer, this is how we recycle obsolete
4745                         // buffers after they are no longer in use
4746                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4747                         while (*p)
4748                         {
4749                                 mem = *p;
4750                                 *p = (*p)->purge;
4751                                 if (mem->buffer)
4752                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4753                                 Mem_Free(mem);
4754                         }
4755                         // reset the current offset
4756                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4757                 }
4758         }
4759 }
4760
4761 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4762 {
4763         r_bufferdata_buffer_t *mem;
4764         int offset = 0;
4765         int padsize;
4766
4767         *returnbufferoffset = 0;
4768
4769         // align size to a byte boundary appropriate for the buffer type, this
4770         // makes all allocations have aligned start offsets
4771         if (type == R_BUFFERDATA_UNIFORM)
4772                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4773         else
4774                 padsize = (datasize + 15) & ~15;
4775
4776         // if we ran out of space in this buffer we must allocate a new one
4777         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)
4778                 R_BufferData_Resize(type, true, padsize);
4779
4780         // if the resize did not give us enough memory, fail
4781         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)
4782                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4783
4784         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4785         offset = (int)mem->current;
4786         mem->current += padsize;
4787
4788         // upload the data to the buffer at the chosen offset
4789         if (offset == 0)
4790                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4791         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4792
4793         // count the usage for stats
4794         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4795         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4796
4797         // return the buffer offset
4798         *returnbufferoffset = offset;
4799
4800         return mem->buffer;
4801 }
4802
4803 //==================================================================================
4804
4805 // LordHavoc: animcache originally written by Echon, rewritten since then
4806
4807 /**
4808  * Animation cache prevents re-generating mesh data for an animated model
4809  * multiple times in one frame for lighting, shadowing, reflections, etc.
4810  */
4811
4812 void R_AnimCache_Free(void)
4813 {
4814 }
4815
4816 void R_AnimCache_ClearCache(void)
4817 {
4818         int i;
4819         entity_render_t *ent;
4820
4821         for (i = 0;i < r_refdef.scene.numentities;i++)
4822         {
4823                 ent = r_refdef.scene.entities[i];
4824                 ent->animcache_vertex3f = NULL;
4825                 ent->animcache_vertex3f_vertexbuffer = NULL;
4826                 ent->animcache_vertex3f_bufferoffset = 0;
4827                 ent->animcache_normal3f = NULL;
4828                 ent->animcache_normal3f_vertexbuffer = NULL;
4829                 ent->animcache_normal3f_bufferoffset = 0;
4830                 ent->animcache_svector3f = NULL;
4831                 ent->animcache_svector3f_vertexbuffer = NULL;
4832                 ent->animcache_svector3f_bufferoffset = 0;
4833                 ent->animcache_tvector3f = NULL;
4834                 ent->animcache_tvector3f_vertexbuffer = NULL;
4835                 ent->animcache_tvector3f_bufferoffset = 0;
4836                 ent->animcache_vertexmesh = NULL;
4837                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4838                 ent->animcache_vertexmesh_bufferoffset = 0;
4839                 ent->animcache_skeletaltransform3x4 = NULL;
4840                 ent->animcache_skeletaltransform3x4buffer = NULL;
4841                 ent->animcache_skeletaltransform3x4offset = 0;
4842                 ent->animcache_skeletaltransform3x4size = 0;
4843         }
4844 }
4845
4846 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4847 {
4848         int i;
4849
4850         // check if we need the meshbuffers
4851         if (!vid.useinterleavedarrays)
4852                 return;
4853
4854         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4855                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4856         // TODO: upload vertexbuffer?
4857         if (ent->animcache_vertexmesh)
4858         {
4859                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4860                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4861                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4862                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4863                 for (i = 0;i < numvertices;i++)
4864                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4865                 if (ent->animcache_svector3f)
4866                         for (i = 0;i < numvertices;i++)
4867                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4868                 if (ent->animcache_tvector3f)
4869                         for (i = 0;i < numvertices;i++)
4870                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4871                 if (ent->animcache_normal3f)
4872                         for (i = 0;i < numvertices;i++)
4873                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4874         }
4875 }
4876
4877 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4878 {
4879         dp_model_t *model = ent->model;
4880         int numvertices;
4881
4882         // see if this ent is worth caching
4883         if (!model || !model->Draw || !model->AnimateVertices)
4884                 return false;
4885         // nothing to cache if it contains no animations and has no skeleton
4886         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4887                 return false;
4888         // see if it is already cached for gpuskeletal
4889         if (ent->animcache_skeletaltransform3x4)
4890                 return false;
4891         // see if it is already cached as a mesh
4892         if (ent->animcache_vertex3f)
4893         {
4894                 // check if we need to add normals or tangents
4895                 if (ent->animcache_normal3f)
4896                         wantnormals = false;
4897                 if (ent->animcache_svector3f)
4898                         wanttangents = false;
4899                 if (!wantnormals && !wanttangents)
4900                         return false;
4901         }
4902
4903         // check which kind of cache we need to generate
4904         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4905         {
4906                 // cache the skeleton so the vertex shader can use it
4907                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4908                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4909                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4910                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4911                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4912                 // note: this can fail if the buffer is at the grow limit
4913                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4914                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4915         }
4916         else if (ent->animcache_vertex3f)
4917         {
4918                 // mesh was already cached but we may need to add normals/tangents
4919                 // (this only happens with multiple views, reflections, cameras, etc)
4920                 if (wantnormals || wanttangents)
4921                 {
4922                         numvertices = model->surfmesh.num_vertices;
4923                         if (wantnormals)
4924                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4925                         if (wanttangents)
4926                         {
4927                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4928                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4929                         }
4930                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4931                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4932                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4933                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4934                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4935                 }
4936         }
4937         else
4938         {
4939                 // generate mesh cache
4940                 numvertices = model->surfmesh.num_vertices;
4941                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4942                 if (wantnormals)
4943                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4944                 if (wanttangents)
4945                 {
4946                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4947                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4948                 }
4949                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4950                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4951                 if (wantnormals || wanttangents)
4952                 {
4953                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4954                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4955                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4956                 }
4957                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4958                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4959                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4960         }
4961         return true;
4962 }
4963
4964 void R_AnimCache_CacheVisibleEntities(void)
4965 {
4966         int i;
4967         qboolean wantnormals = true;
4968         qboolean wanttangents = !r_showsurfaces.integer;
4969
4970         switch(vid.renderpath)
4971         {
4972         case RENDERPATH_GL20:
4973         case RENDERPATH_D3D9:
4974         case RENDERPATH_D3D10:
4975         case RENDERPATH_D3D11:
4976         case RENDERPATH_GLES2:
4977                 break;
4978         case RENDERPATH_GL11:
4979         case RENDERPATH_GL13:
4980         case RENDERPATH_GLES1:
4981                 wanttangents = false;
4982                 break;
4983         case RENDERPATH_SOFT:
4984                 break;
4985         }
4986
4987         if (r_shownormals.integer)
4988                 wanttangents = wantnormals = true;
4989
4990         // TODO: thread this
4991         // NOTE: R_PrepareRTLights() also caches entities
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994                 if (r_refdef.viewcache.entityvisible[i])
4995                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4996 }
4997
4998 //==================================================================================
4999
5000 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5001 {
5002         int i;
5003         vec3_t eyemins, eyemaxs;
5004         vec3_t boxmins, boxmaxs;
5005         vec3_t start;
5006         vec3_t end;
5007         dp_model_t *model = r_refdef.scene.worldmodel;
5008         static vec3_t positions[] = {
5009                 { 0.5f, 0.5f, 0.5f },
5010                 { 0.0f, 0.0f, 0.0f },
5011                 { 0.0f, 0.0f, 1.0f },
5012                 { 0.0f, 1.0f, 0.0f },
5013                 { 0.0f, 1.0f, 1.0f },
5014                 { 1.0f, 0.0f, 0.0f },
5015                 { 1.0f, 0.0f, 1.0f },
5016                 { 1.0f, 1.0f, 0.0f },
5017                 { 1.0f, 1.0f, 1.0f },
5018         };
5019
5020         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5021         if (numsamples < 0)
5022                 return true;
5023
5024         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5025         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5026                 return true;
5027
5028         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5029                 return true;
5030
5031         // expand the eye box a little
5032         eyemins[0] = eye[0] - eyejitter;
5033         eyemaxs[0] = eye[0] + eyejitter;
5034         eyemins[1] = eye[1] - eyejitter;
5035         eyemaxs[1] = eye[1] + eyejitter;
5036         eyemins[2] = eye[2] - eyejitter;
5037         eyemaxs[2] = eye[2] + eyejitter;
5038         // expand the box a little
5039         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5040         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5041         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5042         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5043         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5044         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5045
5046         // return true if eye overlaps enlarged box
5047         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5048                 return true;
5049
5050         // try specific positions in the box first - note that these can be cached
5051         if (r_cullentities_trace_entityocclusion.integer)
5052         {
5053                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5054                 {
5055                         VectorCopy(eye, start);
5056                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5057                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5058                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5059                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5060                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5061                         // not picky - if the trace ended anywhere in the box we're good
5062                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5063                                 return true;
5064                 }
5065         }
5066         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5067                 return true;
5068
5069         // try various random positions
5070         for (i = 0; i < numsamples; i++)
5071         {
5072                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5073                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5074                 if (r_cullentities_trace_entityocclusion.integer)
5075                 {
5076                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5077                         // not picky - if the trace ended anywhere in the box we're good
5078                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5079                                 return true;
5080                 }
5081                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5082                         return true;
5083         }
5084
5085         return false;
5086 }
5087
5088
5089 static void R_View_UpdateEntityVisible (void)
5090 {
5091         int i;
5092         int renderimask;
5093         int samples;
5094         entity_render_t *ent;
5095
5096         if (r_refdef.envmap || r_fb.water.hideplayer)
5097                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5098         else if (chase_active.integer || r_fb.water.renderingscene)
5099                 renderimask = RENDER_VIEWMODEL;
5100         else
5101                 renderimask = RENDER_EXTERIORMODEL;
5102         if (!r_drawviewmodel.integer)
5103                 renderimask |= RENDER_VIEWMODEL;
5104         if (!r_drawexteriormodel.integer)
5105                 renderimask |= RENDER_EXTERIORMODEL;
5106         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5107         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5108         {
5109                 // worldmodel can check visibility
5110                 for (i = 0;i < r_refdef.scene.numentities;i++)
5111                 {
5112                         ent = r_refdef.scene.entities[i];
5113                         if (!(ent->flags & renderimask))
5114                         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)))
5115                         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))
5116                                 r_refdef.viewcache.entityvisible[i] = true;
5117                 }
5118         }
5119         else
5120         {
5121                 // no worldmodel or it can't check visibility
5122                 for (i = 0;i < r_refdef.scene.numentities;i++)
5123                 {
5124                         ent = r_refdef.scene.entities[i];
5125                         if (!(ent->flags & renderimask))
5126                         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)))
5127                                 r_refdef.viewcache.entityvisible[i] = true;
5128                 }
5129         }
5130         if (r_cullentities_trace.integer)
5131         {
5132                 for (i = 0;i < r_refdef.scene.numentities;i++)
5133                 {
5134                         if (!r_refdef.viewcache.entityvisible[i])
5135                                 continue;
5136                         ent = r_refdef.scene.entities[i];
5137                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5138                         {
5139                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5140                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5141                                         ent->last_trace_visibility = realtime;
5142                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5143                                         r_refdef.viewcache.entityvisible[i] = 0;
5144                         }
5145                 }
5146         }
5147 }
5148
5149 /// only used if skyrendermasked, and normally returns false
5150 static int R_DrawBrushModelsSky (void)
5151 {
5152         int i, sky;
5153         entity_render_t *ent;
5154
5155         sky = false;
5156         for (i = 0;i < r_refdef.scene.numentities;i++)
5157         {
5158                 if (!r_refdef.viewcache.entityvisible[i])
5159                         continue;
5160                 ent = r_refdef.scene.entities[i];
5161                 if (!ent->model || !ent->model->DrawSky)
5162                         continue;
5163                 ent->model->DrawSky(ent);
5164                 sky = true;
5165         }
5166         return sky;
5167 }
5168
5169 static void R_DrawNoModel(entity_render_t *ent);
5170 static void R_DrawModels(void)
5171 {
5172         int i;
5173         entity_render_t *ent;
5174
5175         for (i = 0;i < r_refdef.scene.numentities;i++)
5176         {
5177                 if (!r_refdef.viewcache.entityvisible[i])
5178                         continue;
5179                 ent = r_refdef.scene.entities[i];
5180                 r_refdef.stats[r_stat_entities]++;
5181                 /*
5182                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5183                 {
5184                         vec3_t f, l, u, o;
5185                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5186                         Con_Printf("R_DrawModels\n");
5187                         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]);
5188                         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);
5189                         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);
5190                 }
5191                 */
5192                 if (ent->model && ent->model->Draw != NULL)
5193                         ent->model->Draw(ent);
5194                 else
5195                         R_DrawNoModel(ent);
5196         }
5197 }
5198
5199 static void R_DrawModelsDepth(void)
5200 {
5201         int i;
5202         entity_render_t *ent;
5203
5204         for (i = 0;i < r_refdef.scene.numentities;i++)
5205         {
5206                 if (!r_refdef.viewcache.entityvisible[i])
5207                         continue;
5208                 ent = r_refdef.scene.entities[i];
5209                 if (ent->model && ent->model->DrawDepth != NULL)
5210                         ent->model->DrawDepth(ent);
5211         }
5212 }
5213
5214 static void R_DrawModelsDebug(void)
5215 {
5216         int i;
5217         entity_render_t *ent;
5218
5219         for (i = 0;i < r_refdef.scene.numentities;i++)
5220         {
5221                 if (!r_refdef.viewcache.entityvisible[i])
5222                         continue;
5223                 ent = r_refdef.scene.entities[i];
5224                 if (ent->model && ent->model->DrawDebug != NULL)
5225                         ent->model->DrawDebug(ent);
5226         }
5227 }
5228
5229 static void R_DrawModelsAddWaterPlanes(void)
5230 {
5231         int i;
5232         entity_render_t *ent;
5233
5234         for (i = 0;i < r_refdef.scene.numentities;i++)
5235         {
5236                 if (!r_refdef.viewcache.entityvisible[i])
5237                         continue;
5238                 ent = r_refdef.scene.entities[i];
5239                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5240                         ent->model->DrawAddWaterPlanes(ent);
5241         }
5242 }
5243
5244 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}};
5245
5246 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5247 {
5248         if (r_hdr_irisadaptation.integer)
5249         {
5250                 vec3_t p;
5251                 vec3_t ambient;
5252                 vec3_t diffuse;
5253                 vec3_t diffusenormal;
5254                 vec3_t forward;
5255                 vec_t brightness = 0.0f;
5256                 vec_t goal;
5257                 vec_t current;
5258                 vec_t d;
5259                 int c;
5260                 VectorCopy(r_refdef.view.forward, forward);
5261                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5262                 {
5263                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5264                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5265                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5266                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5267                         d = DotProduct(forward, diffusenormal);
5268                         brightness += VectorLength(ambient);
5269                         if (d > 0)
5270                                 brightness += d * VectorLength(diffuse);
5271                 }
5272                 brightness *= 1.0f / c;
5273                 brightness += 0.00001f; // make sure it's never zero
5274                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5275                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5276                 current = r_hdr_irisadaptation_value.value;
5277                 if (current < goal)
5278                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5279                 else if (current > goal)
5280                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5281                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5282                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5283         }
5284         else if (r_hdr_irisadaptation_value.value != 1.0f)
5285                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5286 }
5287
5288 static void R_View_SetFrustum(const int *scissor)
5289 {
5290         int i;
5291         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5292         vec3_t forward, left, up, origin, v;
5293
5294         if(scissor)
5295         {
5296                 // flipped x coordinates (because x points left here)
5297                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5298                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5299
5300                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5301                 switch(vid.renderpath)
5302                 {
5303                         case RENDERPATH_D3D9:
5304                         case RENDERPATH_D3D10:
5305                         case RENDERPATH_D3D11:
5306                                 // non-flipped y coordinates
5307                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5308                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5309                                 break;
5310                         case RENDERPATH_SOFT:
5311                         case RENDERPATH_GL11:
5312                         case RENDERPATH_GL13:
5313                         case RENDERPATH_GL20:
5314                         case RENDERPATH_GLES1:
5315                         case RENDERPATH_GLES2:
5316                                 // non-flipped y coordinates
5317                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5318                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5319                                 break;
5320                 }
5321         }
5322
5323         // we can't trust r_refdef.view.forward and friends in reflected scenes
5324         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5325
5326 #if 0
5327         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5328         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5329         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5330         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5331         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5332         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5333         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5334         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5335         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5336         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5337         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5338         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5339 #endif
5340
5341 #if 0
5342         zNear = r_refdef.nearclip;
5343         nudge = 1.0 - 1.0 / (1<<23);
5344         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5345         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5346         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5347         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5348         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5349         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5350         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5351         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5352 #endif
5353
5354
5355
5356 #if 0
5357         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5358         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5359         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5360         r_refdef.view.frustum[0].dist = m[15] - m[12];
5361
5362         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5363         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5364         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5365         r_refdef.view.frustum[1].dist = m[15] + m[12];
5366
5367         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5368         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5369         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5370         r_refdef.view.frustum[2].dist = m[15] - m[13];
5371
5372         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5373         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5374         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5375         r_refdef.view.frustum[3].dist = m[15] + m[13];
5376
5377         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5378         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5379         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5380         r_refdef.view.frustum[4].dist = m[15] - m[14];
5381
5382         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5383         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5384         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5385         r_refdef.view.frustum[5].dist = m[15] + m[14];
5386 #endif
5387
5388         if (r_refdef.view.useperspective)
5389         {
5390                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5391                 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]);
5392                 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]);
5393                 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]);
5394                 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]);
5395
5396                 // then the normals from the corners relative to origin
5397                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5398                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5399                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5400                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5401
5402                 // in a NORMAL view, forward cross left == up
5403                 // in a REFLECTED view, forward cross left == down
5404                 // so our cross products above need to be adjusted for a left handed coordinate system
5405                 CrossProduct(forward, left, v);
5406                 if(DotProduct(v, up) < 0)
5407                 {
5408                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5409                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5410                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5411                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5412                 }
5413
5414                 // Leaving those out was a mistake, those were in the old code, and they
5415                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5416                 // I couldn't reproduce it after adding those normalizations. --blub
5417                 VectorNormalize(r_refdef.view.frustum[0].normal);
5418                 VectorNormalize(r_refdef.view.frustum[1].normal);
5419                 VectorNormalize(r_refdef.view.frustum[2].normal);
5420                 VectorNormalize(r_refdef.view.frustum[3].normal);
5421
5422                 // make the corners absolute
5423                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5424                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5425                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5426                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5427
5428                 // one more normal
5429                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5430
5431                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5432                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5433                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5434                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5435                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5436         }
5437         else
5438         {
5439                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5440                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5441                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5442                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5443                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5444                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5445                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5446                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5447                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5448                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5449         }
5450         r_refdef.view.numfrustumplanes = 5;
5451
5452         if (r_refdef.view.useclipplane)
5453         {
5454                 r_refdef.view.numfrustumplanes = 6;
5455                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5456         }
5457
5458         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5459                 PlaneClassify(r_refdef.view.frustum + i);
5460
5461         // LordHavoc: note to all quake engine coders, Quake had a special case
5462         // for 90 degrees which assumed a square view (wrong), so I removed it,
5463         // Quake2 has it disabled as well.
5464
5465         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5466         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5467         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5468         //PlaneClassify(&frustum[0]);
5469
5470         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5471         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5472         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5473         //PlaneClassify(&frustum[1]);
5474
5475         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5476         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5477         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5478         //PlaneClassify(&frustum[2]);
5479
5480         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5481         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5482         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5483         //PlaneClassify(&frustum[3]);
5484
5485         // nearclip plane
5486         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5487         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5488         //PlaneClassify(&frustum[4]);
5489 }
5490
5491 static void R_View_UpdateWithScissor(const int *myscissor)
5492 {
5493         R_Main_ResizeViewCache();
5494         R_View_SetFrustum(myscissor);
5495         R_View_WorldVisibility(r_refdef.view.useclipplane);
5496         R_View_UpdateEntityVisible();
5497 }
5498
5499 static void R_View_Update(void)
5500 {
5501         R_Main_ResizeViewCache();
5502         R_View_SetFrustum(NULL);
5503         R_View_WorldVisibility(r_refdef.view.useclipplane);
5504         R_View_UpdateEntityVisible();
5505 }
5506
5507 float viewscalefpsadjusted = 1.0f;
5508
5509 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5510 {
5511         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5512         scale = bound(0.03125f, scale, 1.0f);
5513         *outwidth = (int)ceil(width * scale);
5514         *outheight = (int)ceil(height * scale);
5515 }
5516
5517 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5518 {
5519         const float *customclipplane = NULL;
5520         float plane[4];
5521         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5522         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5523         {
5524                 // LordHavoc: couldn't figure out how to make this approach the
5525                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5526                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5527                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5528                         dist = r_refdef.view.clipplane.dist;
5529                 plane[0] = r_refdef.view.clipplane.normal[0];
5530                 plane[1] = r_refdef.view.clipplane.normal[1];
5531                 plane[2] = r_refdef.view.clipplane.normal[2];
5532                 plane[3] = -dist;
5533                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5534         }
5535
5536         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5537         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5538
5539         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5540         if (!r_refdef.view.useperspective)
5541                 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);
5542         else if (vid.stencil && r_useinfinitefarclip.integer)
5543                 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);
5544         else
5545                 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);
5546         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5547         R_SetViewport(&r_refdef.view.viewport);
5548         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5549         {
5550                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5551                 float screenplane[4];
5552                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5553                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5554                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5555                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5556                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5557         }
5558 }
5559
5560 void R_EntityMatrix(const matrix4x4_t *matrix)
5561 {
5562         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5563         {
5564                 gl_modelmatrixchanged = false;
5565                 gl_modelmatrix = *matrix;
5566                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5567                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5568                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5569                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5570                 CHECKGLERROR
5571                 switch(vid.renderpath)
5572                 {
5573                 case RENDERPATH_D3D9:
5574 #ifdef SUPPORTD3D
5575                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5576                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5577 #endif
5578                         break;
5579                 case RENDERPATH_D3D10:
5580                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5581                         break;
5582                 case RENDERPATH_D3D11:
5583                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5584                         break;
5585                 case RENDERPATH_GL11:
5586                 case RENDERPATH_GL13:
5587                 case RENDERPATH_GLES1:
5588 #ifndef USE_GLES2
5589                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5590 #endif
5591                         break;
5592                 case RENDERPATH_SOFT:
5593                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5594                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5595                         break;
5596                 case RENDERPATH_GL20:
5597                 case RENDERPATH_GLES2:
5598                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5599                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5600                         break;
5601                 }
5602         }
5603 }
5604
5605 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5606 {
5607         r_viewport_t viewport;
5608
5609         CHECKGLERROR
5610
5611         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5612         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);
5613         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5614         R_SetViewport(&viewport);
5615         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5616         GL_Color(1, 1, 1, 1);
5617         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5618         GL_BlendFunc(GL_ONE, GL_ZERO);
5619         GL_ScissorTest(false);
5620         GL_DepthMask(false);
5621         GL_DepthRange(0, 1);
5622         GL_DepthTest(false);
5623         GL_DepthFunc(GL_LEQUAL);
5624         R_EntityMatrix(&identitymatrix);
5625         R_Mesh_ResetTextureState();
5626         GL_PolygonOffset(0, 0);
5627         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5628         switch(vid.renderpath)
5629         {
5630         case RENDERPATH_GL11:
5631         case RENDERPATH_GL13:
5632         case RENDERPATH_GL20:
5633         case RENDERPATH_GLES1:
5634         case RENDERPATH_GLES2:
5635                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5636                 break;
5637         case RENDERPATH_D3D9:
5638         case RENDERPATH_D3D10:
5639         case RENDERPATH_D3D11:
5640         case RENDERPATH_SOFT:
5641                 break;
5642         }
5643         GL_CullFace(GL_NONE);
5644
5645         CHECKGLERROR
5646 }
5647
5648 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5649 {
5650         DrawQ_Finish();
5651
5652         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5653 }
5654
5655 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5656 {
5657         DrawQ_Finish();
5658
5659         R_SetupView(true, fbo, depthtexture, colortexture);
5660         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5661         GL_Color(1, 1, 1, 1);
5662         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5663         GL_BlendFunc(GL_ONE, GL_ZERO);
5664         GL_ScissorTest(true);
5665         GL_DepthMask(true);
5666         GL_DepthRange(0, 1);
5667         GL_DepthTest(true);
5668         GL_DepthFunc(GL_LEQUAL);
5669         R_EntityMatrix(&identitymatrix);
5670         R_Mesh_ResetTextureState();
5671         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5672         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5673         switch(vid.renderpath)
5674         {
5675         case RENDERPATH_GL11:
5676         case RENDERPATH_GL13:
5677         case RENDERPATH_GL20:
5678         case RENDERPATH_GLES1:
5679         case RENDERPATH_GLES2:
5680                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5681                 break;
5682         case RENDERPATH_D3D9:
5683         case RENDERPATH_D3D10:
5684         case RENDERPATH_D3D11:
5685         case RENDERPATH_SOFT:
5686                 break;
5687         }
5688         GL_CullFace(r_refdef.view.cullface_back);
5689 }
5690
5691 /*
5692 ================
5693 R_RenderView_UpdateViewVectors
5694 ================
5695 */
5696 void R_RenderView_UpdateViewVectors(void)
5697 {
5698         // break apart the view matrix into vectors for various purposes
5699         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5700         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5701         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5702         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5703         // make an inverted copy of the view matrix for tracking sprites
5704         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5705 }
5706
5707 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5708 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5709
5710 static void R_Water_StartFrame(void)
5711 {
5712         int i;
5713         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5714         r_waterstate_waterplane_t *p;
5715         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;
5716
5717         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5718                 return;
5719
5720         switch(vid.renderpath)
5721         {
5722         case RENDERPATH_GL20:
5723         case RENDERPATH_D3D9:
5724         case RENDERPATH_D3D10:
5725         case RENDERPATH_D3D11:
5726         case RENDERPATH_SOFT:
5727         case RENDERPATH_GLES2:
5728                 break;
5729         case RENDERPATH_GL11:
5730         case RENDERPATH_GL13:
5731         case RENDERPATH_GLES1:
5732                 return;
5733         }
5734
5735         // set waterwidth and waterheight to the water resolution that will be
5736         // used (often less than the screen resolution for faster rendering)
5737         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5738
5739         // calculate desired texture sizes
5740         // can't use water if the card does not support the texture size
5741         if (!r_water.integer || r_showsurfaces.integer)
5742                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5743         else if (vid.support.arb_texture_non_power_of_two)
5744         {
5745                 texturewidth = waterwidth;
5746                 textureheight = waterheight;
5747                 camerawidth = waterwidth;
5748                 cameraheight = waterheight;
5749         }
5750         else
5751         {
5752                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5753                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5754                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5755                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5756         }
5757
5758         // allocate textures as needed
5759         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))
5760         {
5761                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5762                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5763                 {
5764                         if (p->texture_refraction)
5765                                 R_FreeTexture(p->texture_refraction);
5766                         p->texture_refraction = NULL;
5767                         if (p->fbo_refraction)
5768                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5769                         p->fbo_refraction = 0;
5770                         if (p->texture_reflection)
5771                                 R_FreeTexture(p->texture_reflection);
5772                         p->texture_reflection = NULL;
5773                         if (p->fbo_reflection)
5774                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5775                         p->fbo_reflection = 0;
5776                         if (p->texture_camera)
5777                                 R_FreeTexture(p->texture_camera);
5778                         p->texture_camera = NULL;
5779                         if (p->fbo_camera)
5780                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5781                         p->fbo_camera = 0;
5782                 }
5783                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5784                 r_fb.water.texturewidth = texturewidth;
5785                 r_fb.water.textureheight = textureheight;
5786                 r_fb.water.camerawidth = camerawidth;
5787                 r_fb.water.cameraheight = cameraheight;
5788         }
5789
5790         if (r_fb.water.texturewidth)
5791         {
5792                 int scaledwidth, scaledheight;
5793
5794                 r_fb.water.enabled = true;
5795
5796                 // water resolution is usually reduced
5797                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5798                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5799                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5800
5801                 // set up variables that will be used in shader setup
5802                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5803                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5804                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5805                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5806         }
5807
5808         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5809         r_fb.water.numwaterplanes = 0;
5810 }
5811
5812 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5813 {
5814         int planeindex, bestplaneindex, vertexindex;
5815         vec3_t mins, maxs, normal, center, v, n;
5816         vec_t planescore, bestplanescore;
5817         mplane_t plane;
5818         r_waterstate_waterplane_t *p;
5819         texture_t *t = R_GetCurrentTexture(surface->texture);
5820
5821         rsurface.texture = t;
5822         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5823         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5824         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5825                 return;
5826         // average the vertex normals, find the surface bounds (after deformvertexes)
5827         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5828         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5829         VectorCopy(n, normal);
5830         VectorCopy(v, mins);
5831         VectorCopy(v, maxs);
5832         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5833         {
5834                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5835                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5836                 VectorAdd(normal, n, normal);
5837                 mins[0] = min(mins[0], v[0]);
5838                 mins[1] = min(mins[1], v[1]);
5839                 mins[2] = min(mins[2], v[2]);
5840                 maxs[0] = max(maxs[0], v[0]);
5841                 maxs[1] = max(maxs[1], v[1]);
5842                 maxs[2] = max(maxs[2], v[2]);
5843         }
5844         VectorNormalize(normal);
5845         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5846
5847         VectorCopy(normal, plane.normal);
5848         VectorNormalize(plane.normal);
5849         plane.dist = DotProduct(center, plane.normal);
5850         PlaneClassify(&plane);
5851         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5852         {
5853                 // skip backfaces (except if nocullface is set)
5854 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5855 //                      return;
5856                 VectorNegate(plane.normal, plane.normal);
5857                 plane.dist *= -1;
5858                 PlaneClassify(&plane);
5859         }
5860
5861
5862         // find a matching plane if there is one
5863         bestplaneindex = -1;
5864         bestplanescore = 1048576.0f;
5865         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5866         {
5867                 if(p->camera_entity == t->camera_entity)
5868                 {
5869                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5870                         if (bestplaneindex < 0 || bestplanescore > planescore)
5871                         {
5872                                 bestplaneindex = planeindex;
5873                                 bestplanescore = planescore;
5874                         }
5875                 }
5876         }
5877         planeindex = bestplaneindex;
5878
5879         // if this surface does not fit any known plane rendered this frame, add one
5880         if (planeindex < 0 || bestplanescore > 0.001f)
5881         {
5882                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5883                 {
5884                         // store the new plane
5885                         planeindex = r_fb.water.numwaterplanes++;
5886                         p = r_fb.water.waterplanes + planeindex;
5887                         p->plane = plane;
5888                         // clear materialflags and pvs
5889                         p->materialflags = 0;
5890                         p->pvsvalid = false;
5891                         p->camera_entity = t->camera_entity;
5892                         VectorCopy(mins, p->mins);
5893                         VectorCopy(maxs, p->maxs);
5894                 }
5895                 else
5896                 {
5897                         // We're totally screwed.
5898                         return;
5899                 }
5900         }
5901         else
5902         {
5903                 // merge mins/maxs when we're adding this surface to the plane
5904                 p = r_fb.water.waterplanes + planeindex;
5905                 p->mins[0] = min(p->mins[0], mins[0]);
5906                 p->mins[1] = min(p->mins[1], mins[1]);
5907                 p->mins[2] = min(p->mins[2], mins[2]);
5908                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5909                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5910                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5911         }
5912         // merge this surface's materialflags into the waterplane
5913         p->materialflags |= t->currentmaterialflags;
5914         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5915         {
5916                 // merge this surface's PVS into the waterplane
5917                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5918                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5919                 {
5920                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5921                         p->pvsvalid = true;
5922                 }
5923         }
5924 }
5925
5926 extern cvar_t r_drawparticles;
5927 extern cvar_t r_drawdecals;
5928
5929 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5930 {
5931         int myscissor[4];
5932         r_refdef_view_t originalview;
5933         r_refdef_view_t myview;
5934         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;
5935         r_waterstate_waterplane_t *p;
5936         vec3_t visorigin;
5937         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;
5938         char vabuf[1024];
5939
5940         originalview = r_refdef.view;
5941
5942         // lowquality hack, temporarily shut down some cvars and restore afterwards
5943         qualityreduction = r_water_lowquality.integer;
5944         if (qualityreduction > 0)
5945         {
5946                 if (qualityreduction >= 1)
5947                 {
5948                         old_r_shadows = r_shadows.integer;
5949                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5950                         old_r_dlight = r_shadow_realtime_dlight.integer;
5951                         Cvar_SetValueQuick(&r_shadows, 0);
5952                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5953                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5954                 }
5955                 if (qualityreduction >= 2)
5956                 {
5957                         old_r_dynamic = r_dynamic.integer;
5958                         old_r_particles = r_drawparticles.integer;
5959                         old_r_decals = r_drawdecals.integer;
5960                         Cvar_SetValueQuick(&r_dynamic, 0);
5961                         Cvar_SetValueQuick(&r_drawparticles, 0);
5962                         Cvar_SetValueQuick(&r_drawdecals, 0);
5963                 }
5964         }
5965
5966         // make sure enough textures are allocated
5967         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5968         {
5969                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
5970                         continue;
5971                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5972                 {
5973                         if (!p->texture_refraction)
5974                                 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);
5975                         if (!p->texture_refraction)
5976                                 goto error;
5977                         if (usewaterfbo)
5978                         {
5979                                 if (r_fb.water.depthtexture == NULL)
5980                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5981                                 if (p->fbo_refraction == 0)
5982                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5983                         }
5984                 }
5985                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5986                 {
5987                         if (!p->texture_camera)
5988                                 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);
5989                         if (!p->texture_camera)
5990                                 goto error;
5991                         if (usewaterfbo)
5992                         {
5993                                 if (r_fb.water.depthtexture == NULL)
5994                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5995                                 if (p->fbo_camera == 0)
5996                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5997                         }
5998                 }
5999
6000                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6001                 {
6002                         if (!p->texture_reflection)
6003                                 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);
6004                         if (!p->texture_reflection)
6005                                 goto error;
6006                         if (usewaterfbo)
6007                         {
6008                                 if (r_fb.water.depthtexture == NULL)
6009                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6010                                 if (p->fbo_reflection == 0)
6011                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6012                         }
6013                 }
6014         }
6015
6016         // render views
6017         r_refdef.view = originalview;
6018         r_refdef.view.showdebug = false;
6019         r_refdef.view.width = r_fb.water.waterwidth;
6020         r_refdef.view.height = r_fb.water.waterheight;
6021         r_refdef.view.useclipplane = true;
6022         myview = r_refdef.view;
6023         r_fb.water.renderingscene = true;
6024         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6025         {
6026                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6027                         continue;
6028                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6029                 {
6030                         r_refdef.view = myview;
6031                         if(r_water_scissormode.integer)
6032                         {
6033                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6034                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6035                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6036                         }
6037
6038                         // render reflected scene and copy into texture
6039                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6040                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6041                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6042                         r_refdef.view.clipplane = p->plane;
6043                         // reverse the cullface settings for this render
6044                         r_refdef.view.cullface_front = GL_FRONT;
6045                         r_refdef.view.cullface_back = GL_BACK;
6046                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6047                         {
6048                                 r_refdef.view.usecustompvs = true;
6049                                 if (p->pvsvalid)
6050                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6051                                 else
6052                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6053                         }
6054
6055                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6056                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6057                         R_ClearScreen(r_refdef.fogenabled);
6058                         if(r_water_scissormode.integer & 2)
6059                                 R_View_UpdateWithScissor(myscissor);
6060                         else
6061                                 R_View_Update();
6062                         R_AnimCache_CacheVisibleEntities();
6063                         if(r_water_scissormode.integer & 1)
6064                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6065                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6066
6067                         if (!p->fbo_reflection)
6068                                 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);
6069                         r_fb.water.hideplayer = false;
6070                 }
6071
6072                 // render the normal view scene and copy into texture
6073                 // (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)
6074                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6075                 {
6076                         r_refdef.view = myview;
6077                         if(r_water_scissormode.integer)
6078                         {
6079                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6080                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6081                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6082                         }
6083
6084                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6085
6086                         r_refdef.view.clipplane = p->plane;
6087                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6088                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6089
6090                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6091                         {
6092                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6093                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6094                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6095                                 R_RenderView_UpdateViewVectors();
6096                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6097                                 {
6098                                         r_refdef.view.usecustompvs = true;
6099                                         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);
6100                                 }
6101                         }
6102
6103                         PlaneClassify(&r_refdef.view.clipplane);
6104
6105                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6106                         R_ClearScreen(r_refdef.fogenabled);
6107                         if(r_water_scissormode.integer & 2)
6108                                 R_View_UpdateWithScissor(myscissor);
6109                         else
6110                                 R_View_Update();
6111                         R_AnimCache_CacheVisibleEntities();
6112                         if(r_water_scissormode.integer & 1)
6113                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6114                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6115
6116                         if (!p->fbo_refraction)
6117                                 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);
6118                         r_fb.water.hideplayer = false;
6119                 }
6120                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6121                 {
6122                         r_refdef.view = myview;
6123
6124                         r_refdef.view.clipplane = p->plane;
6125                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6126                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6127
6128                         r_refdef.view.width = r_fb.water.camerawidth;
6129                         r_refdef.view.height = r_fb.water.cameraheight;
6130                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6131                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6132                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6133                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6134
6135                         if(p->camera_entity)
6136                         {
6137                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6138                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6139                         }
6140
6141                         // note: all of the view is used for displaying... so
6142                         // there is no use in scissoring
6143
6144                         // reverse the cullface settings for this render
6145                         r_refdef.view.cullface_front = GL_FRONT;
6146                         r_refdef.view.cullface_back = GL_BACK;
6147                         // also reverse the view matrix
6148                         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
6149                         R_RenderView_UpdateViewVectors();
6150                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6151                         {
6152                                 r_refdef.view.usecustompvs = true;
6153                                 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);
6154                         }
6155                         
6156                         // camera needs no clipplane
6157                         r_refdef.view.useclipplane = false;
6158
6159                         PlaneClassify(&r_refdef.view.clipplane);
6160
6161                         r_fb.water.hideplayer = false;
6162
6163                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6164                         R_ClearScreen(r_refdef.fogenabled);
6165                         R_View_Update();
6166                         R_AnimCache_CacheVisibleEntities();
6167                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6168
6169                         if (!p->fbo_camera)
6170                                 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);
6171                         r_fb.water.hideplayer = false;
6172                 }
6173
6174         }
6175         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6176         r_fb.water.renderingscene = false;
6177         r_refdef.view = originalview;
6178         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6179         if (!r_fb.water.depthtexture)
6180                 R_ClearScreen(r_refdef.fogenabled);
6181         R_View_Update();
6182         R_AnimCache_CacheVisibleEntities();
6183         goto finish;
6184 error:
6185         r_refdef.view = originalview;
6186         r_fb.water.renderingscene = false;
6187         Cvar_SetValueQuick(&r_water, 0);
6188         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6189 finish:
6190         // lowquality hack, restore cvars
6191         if (qualityreduction > 0)
6192         {
6193                 if (qualityreduction >= 1)
6194                 {
6195                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6196                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6197                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6198                 }
6199                 if (qualityreduction >= 2)
6200                 {
6201                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6202                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6203                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6204                 }
6205         }
6206 }
6207
6208 static void R_Bloom_StartFrame(void)
6209 {
6210         int i;
6211         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6212         int viewwidth, viewheight;
6213         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6214         textype_t textype = TEXTYPE_COLORBUFFER;
6215
6216         switch (vid.renderpath)
6217         {
6218         case RENDERPATH_GL20:
6219                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6220                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6221                 {
6222                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6223                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6224                 }
6225                 break;
6226         case RENDERPATH_GL11:
6227         case RENDERPATH_GL13:
6228         case RENDERPATH_GLES1:
6229         case RENDERPATH_GLES2:
6230         case RENDERPATH_D3D9:
6231         case RENDERPATH_D3D10:
6232         case RENDERPATH_D3D11:
6233                 r_fb.usedepthtextures = false;
6234                 break;
6235         case RENDERPATH_SOFT:
6236                 r_fb.usedepthtextures = true;
6237                 break;
6238         }
6239
6240         if (r_viewscale_fpsscaling.integer)
6241         {
6242                 double actualframetime;
6243                 double targetframetime;
6244                 double adjust;
6245                 actualframetime = r_refdef.lastdrawscreentime;
6246                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6247                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6248                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6249                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6250                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6251                 viewscalefpsadjusted += adjust;
6252                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6253         }
6254         else
6255                 viewscalefpsadjusted = 1.0f;
6256
6257         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6258
6259         switch(vid.renderpath)
6260         {
6261         case RENDERPATH_GL20:
6262         case RENDERPATH_D3D9:
6263         case RENDERPATH_D3D10:
6264         case RENDERPATH_D3D11:
6265         case RENDERPATH_SOFT:
6266         case RENDERPATH_GLES2:
6267                 break;
6268         case RENDERPATH_GL11:
6269         case RENDERPATH_GL13:
6270         case RENDERPATH_GLES1:
6271                 return;
6272         }
6273
6274         // set bloomwidth and bloomheight to the bloom resolution that will be
6275         // used (often less than the screen resolution for faster rendering)
6276         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6277         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6278         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6279         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6280         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6281
6282         // calculate desired texture sizes
6283         if (vid.support.arb_texture_non_power_of_two)
6284         {
6285                 screentexturewidth = vid.width;
6286                 screentextureheight = vid.height;
6287                 bloomtexturewidth = r_fb.bloomwidth;
6288                 bloomtextureheight = r_fb.bloomheight;
6289         }
6290         else
6291         {
6292                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6293                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6294                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6295                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6296         }
6297
6298         if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6299         {
6300                 Cvar_SetValueQuick(&r_bloom, 0);
6301                 Cvar_SetValueQuick(&r_motionblur, 0);
6302                 Cvar_SetValueQuick(&r_damageblur, 0);
6303         }
6304
6305         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6306          && !r_bloom.integer
6307          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6308          && !useviewfbo
6309          && r_viewscale.value == 1.0f
6310          && !r_viewscale_fpsscaling.integer)
6311                 screentexturewidth = screentextureheight = 0;
6312         if (!r_bloom.integer)
6313                 bloomtexturewidth = bloomtextureheight = 0;
6314
6315         // allocate textures as needed
6316         if (r_fb.screentexturewidth != screentexturewidth
6317          || r_fb.screentextureheight != screentextureheight
6318          || r_fb.bloomtexturewidth != bloomtexturewidth
6319          || r_fb.bloomtextureheight != bloomtextureheight
6320          || r_fb.textype != textype
6321          || useviewfbo != (r_fb.fbo != 0))
6322         {
6323                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6324                 {
6325                         if (r_fb.bloomtexture[i])
6326                                 R_FreeTexture(r_fb.bloomtexture[i]);
6327                         r_fb.bloomtexture[i] = NULL;
6328
6329                         if (r_fb.bloomfbo[i])
6330                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6331                         r_fb.bloomfbo[i] = 0;
6332                 }
6333
6334                 if (r_fb.fbo)
6335                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6336                 r_fb.fbo = 0;
6337
6338                 if (r_fb.colortexture)
6339                         R_FreeTexture(r_fb.colortexture);
6340                 r_fb.colortexture = NULL;
6341
6342                 if (r_fb.depthtexture)
6343                         R_FreeTexture(r_fb.depthtexture);
6344                 r_fb.depthtexture = NULL;
6345
6346                 if (r_fb.ghosttexture)
6347                         R_FreeTexture(r_fb.ghosttexture);
6348                 r_fb.ghosttexture = NULL;
6349
6350                 r_fb.screentexturewidth = screentexturewidth;
6351                 r_fb.screentextureheight = screentextureheight;
6352                 r_fb.bloomtexturewidth = bloomtexturewidth;
6353                 r_fb.bloomtextureheight = bloomtextureheight;
6354                 r_fb.textype = textype;
6355
6356                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6357                 {
6358                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6359                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6360                         r_fb.ghosttexture_valid = false;
6361                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6362                         if (useviewfbo)
6363                         {
6364                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6365                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6366                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6367                         }
6368                 }
6369
6370                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6371                 {
6372                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6373                         {
6374                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6375                                 if (useviewfbo)
6376                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6377                         }
6378                 }
6379         }
6380
6381         // bloom texture is a different resolution
6382         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6383         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6384         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6385         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6386         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6387
6388         // set up a texcoord array for the full resolution screen image
6389         // (we have to keep this around to copy back during final render)
6390         r_fb.screentexcoord2f[0] = 0;
6391         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6392         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6393         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6394         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6395         r_fb.screentexcoord2f[5] = 0;
6396         r_fb.screentexcoord2f[6] = 0;
6397         r_fb.screentexcoord2f[7] = 0;
6398
6399         if(r_fb.fbo) 
6400         {
6401                 for (i = 1;i < 8;i += 2)
6402                 {
6403                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6404                 }
6405         }
6406
6407         // set up a texcoord array for the reduced resolution bloom image
6408         // (which will be additive blended over the screen image)
6409         r_fb.bloomtexcoord2f[0] = 0;
6410         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6411         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6412         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6413         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6414         r_fb.bloomtexcoord2f[5] = 0;
6415         r_fb.bloomtexcoord2f[6] = 0;
6416         r_fb.bloomtexcoord2f[7] = 0;
6417
6418         switch(vid.renderpath)
6419         {
6420         case RENDERPATH_GL11:
6421         case RENDERPATH_GL13:
6422         case RENDERPATH_GL20:
6423         case RENDERPATH_SOFT:
6424         case RENDERPATH_GLES1:
6425         case RENDERPATH_GLES2:
6426                 break;
6427         case RENDERPATH_D3D9:
6428         case RENDERPATH_D3D10:
6429         case RENDERPATH_D3D11:
6430                 for (i = 0;i < 4;i++)
6431                 {
6432                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6433                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6434                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6435                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6436                 }
6437                 break;
6438         }
6439
6440         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6441
6442         if (r_fb.fbo)
6443                 r_refdef.view.clear = true;
6444 }
6445
6446 static void R_Bloom_MakeTexture(void)
6447 {
6448         int x, range, dir;
6449         float xoffset, yoffset, r, brighten;
6450         rtexture_t *intex;
6451         float colorscale = r_bloom_colorscale.value;
6452
6453         r_refdef.stats[r_stat_bloom]++;
6454     
6455 #if 0
6456     // this copy is unnecessary since it happens in R_BlendView already
6457         if (!r_fb.fbo)
6458         {
6459                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6460                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6461         }
6462 #endif
6463
6464         // scale down screen texture to the bloom texture size
6465         CHECKGLERROR
6466         r_fb.bloomindex = 0;
6467         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6468         R_SetViewport(&r_fb.bloomviewport);
6469         GL_CullFace(GL_NONE);
6470         GL_DepthTest(false);
6471         GL_BlendFunc(GL_ONE, GL_ZERO);
6472         GL_Color(colorscale, colorscale, colorscale, 1);
6473         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6474         switch(vid.renderpath)
6475         {
6476         case RENDERPATH_GL11:
6477         case RENDERPATH_GL13:
6478         case RENDERPATH_GL20:
6479         case RENDERPATH_GLES1:
6480         case RENDERPATH_GLES2:
6481         case RENDERPATH_SOFT:
6482                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6483                 break;
6484         case RENDERPATH_D3D9:
6485         case RENDERPATH_D3D10:
6486         case RENDERPATH_D3D11:
6487                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6488                 break;
6489         }
6490         // TODO: do boxfilter scale-down in shader?
6491         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6492         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6493         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6494
6495         // we now have a properly scaled bloom image
6496         if (!r_fb.bloomfbo[r_fb.bloomindex])
6497         {
6498                 // copy it into the bloom texture
6499                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6500                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6501         }
6502
6503         // multiply bloom image by itself as many times as desired
6504         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6505         {
6506                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6507                 r_fb.bloomindex ^= 1;
6508                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6509                 x *= 2;
6510                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6511                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6512                 {
6513                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6514                         GL_Color(r,r,r,1); // apply fix factor
6515                 }
6516                 else
6517                 {
6518                         if(x <= 2)
6519                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6520                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6521                         GL_Color(1,1,1,1); // no fix factor supported here
6522                 }
6523                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6524                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6525                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6526                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6527
6528                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6529                 {
6530                         // copy the darkened image to a texture
6531                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6532                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6533                 }
6534         }
6535
6536         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6537         brighten = r_bloom_brighten.value;
6538         brighten = sqrt(brighten);
6539         if(range >= 1)
6540                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6541
6542         for (dir = 0;dir < 2;dir++)
6543         {
6544                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6545                 r_fb.bloomindex ^= 1;
6546                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6547                 // blend on at multiple vertical offsets to achieve a vertical blur
6548                 // TODO: do offset blends using GLSL
6549                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6550                 GL_BlendFunc(GL_ONE, GL_ZERO);
6551                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6552                 for (x = -range;x <= range;x++)
6553                 {
6554                         if (!dir){xoffset = 0;yoffset = x;}
6555                         else {xoffset = x;yoffset = 0;}
6556                         xoffset /= (float)r_fb.bloomtexturewidth;
6557                         yoffset /= (float)r_fb.bloomtextureheight;
6558                         // compute a texcoord array with the specified x and y offset
6559                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6560                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6561                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6562                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6563                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6564                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6565                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6566                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6567                         // this r value looks like a 'dot' particle, fading sharply to
6568                         // black at the edges
6569                         // (probably not realistic but looks good enough)
6570                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6571                         //r = brighten/(range*2+1);
6572                         r = brighten / (range * 2 + 1);
6573                         if(range >= 1)
6574                                 r *= (1 - x*x/(float)(range*range));
6575                         GL_Color(r, r, r, 1);
6576                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6577                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6578                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6579                         GL_BlendFunc(GL_ONE, GL_ONE);
6580                 }
6581
6582                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6583                 {
6584                         // copy the vertically or horizontally blurred bloom view to a texture
6585                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6586                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6587                 }
6588         }
6589 }
6590
6591 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6592 {
6593         dpuint64 permutation;
6594         float uservecs[4][4];
6595
6596         R_EntityMatrix(&identitymatrix);
6597
6598         switch (vid.renderpath)
6599         {
6600         case RENDERPATH_GL20:
6601         case RENDERPATH_D3D9:
6602         case RENDERPATH_D3D10:
6603         case RENDERPATH_D3D11:
6604         case RENDERPATH_SOFT:
6605         case RENDERPATH_GLES2:
6606                 permutation =
6607                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6608                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6609                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6610                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6611                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6612
6613                 if (r_fb.colortexture)
6614                 {
6615                         if (!r_fb.fbo)
6616                         {
6617                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6618                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6619                         }
6620
6621                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6622                         {
6623                                 // declare variables
6624                                 float blur_factor, blur_mouseaccel, blur_velocity;
6625                                 static float blur_average; 
6626                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6627
6628                                 // set a goal for the factoring
6629                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6630                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6631                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6632                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6633                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6634                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6635
6636                                 // from the goal, pick an averaged value between goal and last value
6637                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6638                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6639
6640                                 // enforce minimum amount of blur 
6641                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6642
6643                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6644
6645                                 // calculate values into a standard alpha
6646                                 cl.motionbluralpha = 1 - exp(-
6647                                                 (
6648                                                  (r_motionblur.value * blur_factor / 80)
6649                                                  +
6650                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6651                                                 )
6652                                                 /
6653                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6654                                           );
6655
6656                                 // randomization for the blur value to combat persistent ghosting
6657                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6658                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6659
6660                                 // apply the blur
6661                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6662                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6663                                 {
6664                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6665                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6666                                         switch(vid.renderpath)
6667                                         {
6668                                         case RENDERPATH_GL11:
6669                                         case RENDERPATH_GL13:
6670                                         case RENDERPATH_GL20:
6671                                         case RENDERPATH_GLES1:
6672                                         case RENDERPATH_GLES2:
6673                                         case RENDERPATH_SOFT:
6674                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6675                                                 break;
6676                                         case RENDERPATH_D3D9:
6677                                         case RENDERPATH_D3D10:
6678                                         case RENDERPATH_D3D11:
6679                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6680                                                 break;
6681                                         }
6682                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6683                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6684                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6685                                 }
6686
6687                                 // updates old view angles for next pass
6688                                 VectorCopy(cl.viewangles, blur_oldangles);
6689
6690                                 // copy view into the ghost texture
6691                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6692                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6693                                 r_fb.ghosttexture_valid = true;
6694                         }
6695                 }
6696                 else
6697                 {
6698                         // no r_fb.colortexture means we're rendering to the real fb
6699                         // we may still have to do view tint...
6700                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6701                         {
6702                                 // apply a color tint to the whole view
6703                                 R_ResetViewRendering2D(0, NULL, NULL);
6704                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6705                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6706                                 R_SetupShader_Generic_NoTexture(false, true);
6707                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6708                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6709                         }
6710                         break; // no screen processing, no bloom, skip it
6711                 }
6712
6713                 if (r_fb.bloomtexture[0])
6714                 {
6715                         // make the bloom texture
6716                         R_Bloom_MakeTexture();
6717                 }
6718
6719 #if _MSC_VER >= 1400
6720 #define sscanf sscanf_s
6721 #endif
6722                 memset(uservecs, 0, sizeof(uservecs));
6723                 if (r_glsl_postprocess_uservec1_enable.integer)
6724                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6725                 if (r_glsl_postprocess_uservec2_enable.integer)
6726                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6727                 if (r_glsl_postprocess_uservec3_enable.integer)
6728                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6729                 if (r_glsl_postprocess_uservec4_enable.integer)
6730                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6731
6732                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6733                 GL_Color(1, 1, 1, 1);
6734                 GL_BlendFunc(GL_ONE, GL_ZERO);
6735
6736                 switch(vid.renderpath)
6737                 {
6738                 case RENDERPATH_GL20:
6739                 case RENDERPATH_GLES2:
6740                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6741                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6742                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6743                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6744                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6745                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6746                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6747                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6748                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6749                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6750                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6751                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6752                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6753                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6754                         break;
6755                 case RENDERPATH_D3D9:
6756 #ifdef SUPPORTD3D
6757                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6758                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6759                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6760                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6761                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6762                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6763                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6764                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6765                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6766                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6767                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6768                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6769                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6770                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6771                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6772 #endif
6773                         break;
6774                 case RENDERPATH_D3D10:
6775                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6776                         break;
6777                 case RENDERPATH_D3D11:
6778                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6779                         break;
6780                 case RENDERPATH_SOFT:
6781                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6782                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6783                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6784                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6785                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6786                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6787                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6788                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6789                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6790                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6791                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6792                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6793                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6794                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6795                         break;
6796                 default:
6797                         break;
6798                 }
6799                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6800                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6801                 break;
6802         case RENDERPATH_GL11:
6803         case RENDERPATH_GL13:
6804         case RENDERPATH_GLES1:
6805                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6806                 {
6807                         // apply a color tint to the whole view
6808                         R_ResetViewRendering2D(0, NULL, NULL);
6809                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6810                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6811                         R_SetupShader_Generic_NoTexture(false, true);
6812                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6813                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6814                 }
6815                 break;
6816         }
6817 }
6818
6819 matrix4x4_t r_waterscrollmatrix;
6820
6821 void R_UpdateFog(void)
6822 {
6823         // Nehahra fog
6824         if (gamemode == GAME_NEHAHRA)
6825         {
6826                 if (gl_fogenable.integer)
6827                 {
6828                         r_refdef.oldgl_fogenable = true;
6829                         r_refdef.fog_density = gl_fogdensity.value;
6830                         r_refdef.fog_red = gl_fogred.value;
6831                         r_refdef.fog_green = gl_foggreen.value;
6832                         r_refdef.fog_blue = gl_fogblue.value;
6833                         r_refdef.fog_alpha = 1;
6834                         r_refdef.fog_start = 0;
6835                         r_refdef.fog_end = gl_skyclip.value;
6836                         r_refdef.fog_height = 1<<30;
6837                         r_refdef.fog_fadedepth = 128;
6838                 }
6839                 else if (r_refdef.oldgl_fogenable)
6840                 {
6841                         r_refdef.oldgl_fogenable = false;
6842                         r_refdef.fog_density = 0;
6843                         r_refdef.fog_red = 0;
6844                         r_refdef.fog_green = 0;
6845                         r_refdef.fog_blue = 0;
6846                         r_refdef.fog_alpha = 0;
6847                         r_refdef.fog_start = 0;
6848                         r_refdef.fog_end = 0;
6849                         r_refdef.fog_height = 1<<30;
6850                         r_refdef.fog_fadedepth = 128;
6851                 }
6852         }
6853
6854         // fog parms
6855         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6856         r_refdef.fog_start = max(0, r_refdef.fog_start);
6857         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6858
6859         if (r_refdef.fog_density && r_drawfog.integer)
6860         {
6861                 r_refdef.fogenabled = true;
6862                 // this is the point where the fog reaches 0.9986 alpha, which we
6863                 // consider a good enough cutoff point for the texture
6864                 // (0.9986 * 256 == 255.6)
6865                 if (r_fog_exp2.integer)
6866                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6867                 else
6868                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6869                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6870                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6871                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6872                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6873                         R_BuildFogHeightTexture();
6874                 // fog color was already set
6875                 // update the fog texture
6876                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6877                         R_BuildFogTexture();
6878                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6879                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6880         }
6881         else
6882                 r_refdef.fogenabled = false;
6883
6884         // fog color
6885         if (r_refdef.fog_density)
6886         {
6887                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6888                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6889                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6890
6891                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6892                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6893                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6894                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6895
6896                 {
6897                         vec3_t fogvec;
6898                         VectorCopy(r_refdef.fogcolor, fogvec);
6899                         //   color.rgb *= ContrastBoost * SceneBrightness;
6900                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6901                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6902                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6903                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6904                 }
6905         }
6906 }
6907
6908 void R_UpdateVariables(void)
6909 {
6910         R_Textures_Frame();
6911
6912         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6913
6914         r_refdef.farclip = r_farclip_base.value;
6915         if (r_refdef.scene.worldmodel)
6916                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6917         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6918
6919         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6920                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6921         r_refdef.polygonfactor = 0;
6922         r_refdef.polygonoffset = 0;
6923         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6924         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6925
6926         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6927         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6928         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6929         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6930         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6931         if (FAKELIGHT_ENABLED)
6932         {
6933                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6934         }
6935         else if (r_refdef.scene.worldmodel)
6936         {
6937                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6938         }
6939         if (r_showsurfaces.integer)
6940         {
6941                 r_refdef.scene.rtworld = false;
6942                 r_refdef.scene.rtworldshadows = false;
6943                 r_refdef.scene.rtdlight = false;
6944                 r_refdef.scene.rtdlightshadows = false;
6945                 r_refdef.scene.lightmapintensity = 0;
6946         }
6947
6948         r_gpuskeletal = false;
6949         switch(vid.renderpath)
6950         {
6951         case RENDERPATH_GL20:
6952                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6953         case RENDERPATH_D3D9:
6954         case RENDERPATH_D3D10:
6955         case RENDERPATH_D3D11:
6956         case RENDERPATH_SOFT:
6957         case RENDERPATH_GLES2:
6958                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6959                 {
6960                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6961                         {
6962                                 // build GLSL gamma texture
6963 #define RAMPWIDTH 256
6964                                 unsigned short ramp[RAMPWIDTH * 3];
6965                                 unsigned char rampbgr[RAMPWIDTH][4];
6966                                 int i;
6967
6968                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6969
6970                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6971                                 for(i = 0; i < RAMPWIDTH; ++i)
6972                                 {
6973                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6974                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6975                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6976                                         rampbgr[i][3] = 0;
6977                                 }
6978                                 if (r_texture_gammaramps)
6979                                 {
6980                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6981                                 }
6982                                 else
6983                                 {
6984                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6985                                 }
6986                         }
6987                 }
6988                 else
6989                 {
6990                         // remove GLSL gamma texture
6991                 }
6992                 break;
6993         case RENDERPATH_GL11:
6994         case RENDERPATH_GL13:
6995         case RENDERPATH_GLES1:
6996                 break;
6997         }
6998 }
6999
7000 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7001 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7002 /*
7003 ================
7004 R_SelectScene
7005 ================
7006 */
7007 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7008         if( scenetype != r_currentscenetype ) {
7009                 // store the old scenetype
7010                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7011                 r_currentscenetype = scenetype;
7012                 // move in the new scene
7013                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7014         }
7015 }
7016
7017 /*
7018 ================
7019 R_GetScenePointer
7020 ================
7021 */
7022 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7023 {
7024         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7025         if( scenetype == r_currentscenetype ) {
7026                 return &r_refdef.scene;
7027         } else {
7028                 return &r_scenes_store[ scenetype ];
7029         }
7030 }
7031
7032 static int R_SortEntities_Compare(const void *ap, const void *bp)
7033 {
7034         const entity_render_t *a = *(const entity_render_t **)ap;
7035         const entity_render_t *b = *(const entity_render_t **)bp;
7036
7037         // 1. compare model
7038         if(a->model < b->model)
7039                 return -1;
7040         if(a->model > b->model)
7041                 return +1;
7042
7043         // 2. compare skin
7044         // TODO possibly calculate the REAL skinnum here first using
7045         // skinscenes?
7046         if(a->skinnum < b->skinnum)
7047                 return -1;
7048         if(a->skinnum > b->skinnum)
7049                 return +1;
7050
7051         // everything we compared is equal
7052         return 0;
7053 }
7054 static void R_SortEntities(void)
7055 {
7056         // below or equal 2 ents, sorting never gains anything
7057         if(r_refdef.scene.numentities <= 2)
7058                 return;
7059         // sort
7060         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7061 }
7062
7063 /*
7064 ================
7065 R_RenderView
7066 ================
7067 */
7068 int dpsoftrast_test;
7069 extern cvar_t r_shadow_bouncegrid;
7070 void R_RenderView(void)
7071 {
7072         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7073         int fbo;
7074         rtexture_t *depthtexture;
7075         rtexture_t *colortexture;
7076
7077         dpsoftrast_test = r_test.integer;
7078
7079         if (r_timereport_active)
7080                 R_TimeReport("start");
7081         r_textureframe++; // used only by R_GetCurrentTexture
7082         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7083
7084         if(R_CompileShader_CheckStaticParms())
7085                 R_GLSL_Restart_f();
7086
7087         if (!r_drawentities.integer)
7088                 r_refdef.scene.numentities = 0;
7089         else if (r_sortentities.integer)
7090                 R_SortEntities();
7091
7092         R_AnimCache_ClearCache();
7093
7094         /* adjust for stereo display */
7095         if(R_Stereo_Active())
7096         {
7097                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
7098                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7099         }
7100
7101         if (r_refdef.view.isoverlay)
7102         {
7103                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7104                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7105                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7106                 R_TimeReport("depthclear");
7107
7108                 r_refdef.view.showdebug = false;
7109
7110                 r_fb.water.enabled = false;
7111                 r_fb.water.numwaterplanes = 0;
7112
7113                 R_RenderScene(0, NULL, NULL);
7114
7115                 r_refdef.view.matrix = originalmatrix;
7116
7117                 CHECKGLERROR
7118                 return;
7119         }
7120
7121         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7122         {
7123                 r_refdef.view.matrix = originalmatrix;
7124                 return;
7125         }
7126
7127         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7128
7129         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7130                 // in sRGB fallback, behave similar to true sRGB: convert this
7131                 // value from linear to sRGB
7132                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7133
7134         R_RenderView_UpdateViewVectors();
7135
7136         R_Shadow_UpdateWorldLightSelection();
7137
7138         R_Bloom_StartFrame();
7139
7140         // apply bloom brightness offset
7141         if(r_fb.bloomtexture[0])
7142                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7143
7144         R_Water_StartFrame();
7145
7146         // now we probably have an fbo to render into
7147         fbo = r_fb.fbo;
7148         depthtexture = r_fb.depthtexture;
7149         colortexture = r_fb.colortexture;
7150
7151         CHECKGLERROR
7152         if (r_timereport_active)
7153                 R_TimeReport("viewsetup");
7154
7155         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7156
7157         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7158         {
7159                 R_ClearScreen(r_refdef.fogenabled);
7160                 if (r_timereport_active)
7161                         R_TimeReport("viewclear");
7162         }
7163         r_refdef.view.clear = true;
7164
7165         r_refdef.view.showdebug = true;
7166
7167         R_View_Update();
7168         if (r_timereport_active)
7169                 R_TimeReport("visibility");
7170
7171         R_AnimCache_CacheVisibleEntities();
7172         if (r_timereport_active)
7173                 R_TimeReport("animcache");
7174
7175         R_Shadow_UpdateBounceGridTexture();
7176         if (r_timereport_active && r_shadow_bouncegrid.integer)
7177                 R_TimeReport("bouncegrid");
7178
7179         r_fb.water.numwaterplanes = 0;
7180         if (r_fb.water.enabled)
7181                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7182
7183         R_RenderScene(fbo, depthtexture, colortexture);
7184         r_fb.water.numwaterplanes = 0;
7185
7186         R_BlendView(fbo, depthtexture, colortexture);
7187         if (r_timereport_active)
7188                 R_TimeReport("blendview");
7189
7190         GL_Scissor(0, 0, vid.width, vid.height);
7191         GL_ScissorTest(false);
7192
7193         r_refdef.view.matrix = originalmatrix;
7194
7195         CHECKGLERROR
7196 }
7197
7198 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7199 {
7200         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7201         {
7202                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7203                 if (r_timereport_active)
7204                         R_TimeReport("waterworld");
7205         }
7206
7207         // don't let sound skip if going slow
7208         if (r_refdef.scene.extraupdate)
7209                 S_ExtraUpdate ();
7210
7211         R_DrawModelsAddWaterPlanes();
7212         if (r_timereport_active)
7213                 R_TimeReport("watermodels");
7214
7215         if (r_fb.water.numwaterplanes)
7216         {
7217                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7218                 if (r_timereport_active)
7219                         R_TimeReport("waterscenes");
7220         }
7221 }
7222
7223 extern cvar_t cl_locs_show;
7224 static void R_DrawLocs(void);
7225 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7226 static void R_DrawModelDecals(void);
7227 extern cvar_t cl_decals_newsystem;
7228 extern qboolean r_shadow_usingdeferredprepass;
7229 extern int r_shadow_shadowmapatlas_modelshadows_size;
7230 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7231 {
7232         qboolean shadowmapping = false;
7233
7234         if (r_timereport_active)
7235                 R_TimeReport("beginscene");
7236
7237         r_refdef.stats[r_stat_renders]++;
7238
7239         R_UpdateFog();
7240
7241         // don't let sound skip if going slow
7242         if (r_refdef.scene.extraupdate)
7243                 S_ExtraUpdate ();
7244
7245         R_MeshQueue_BeginScene();
7246
7247         R_SkyStartFrame();
7248
7249         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7250
7251         if (r_timereport_active)
7252                 R_TimeReport("skystartframe");
7253
7254         if (cl.csqc_vidvars.drawworld)
7255         {
7256                 // don't let sound skip if going slow
7257                 if (r_refdef.scene.extraupdate)
7258                         S_ExtraUpdate ();
7259
7260                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7261                 {
7262                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7263                         if (r_timereport_active)
7264                                 R_TimeReport("worldsky");
7265                 }
7266
7267                 if (R_DrawBrushModelsSky() && r_timereport_active)
7268                         R_TimeReport("bmodelsky");
7269
7270                 if (skyrendermasked && skyrenderlater)
7271                 {
7272                         // we have to force off the water clipping plane while rendering sky
7273                         R_SetupView(false, fbo, depthtexture, colortexture);
7274                         R_Sky();
7275                         R_SetupView(true, fbo, depthtexture, colortexture);
7276                         if (r_timereport_active)
7277                                 R_TimeReport("sky");
7278                 }
7279         }
7280
7281         R_Shadow_PrepareModelShadows();
7282         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7283         if (r_timereport_active)
7284                 R_TimeReport("preparelights");
7285
7286         // render all the shadowmaps that will be used for this view
7287         shadowmapping = R_Shadow_ShadowMappingEnabled();
7288         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7289         {
7290                 R_Shadow_DrawShadowMaps();
7291                 if (r_timereport_active)
7292                         R_TimeReport("shadowmaps");
7293         }
7294
7295         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7296         if (r_shadow_usingdeferredprepass)
7297                 R_Shadow_DrawPrepass();
7298
7299         // now we begin the forward pass of the view render
7300         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7301         {
7302                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7303                 if (r_timereport_active)
7304                         R_TimeReport("worlddepth");
7305         }
7306         if (r_depthfirst.integer >= 2)
7307         {
7308                 R_DrawModelsDepth();
7309                 if (r_timereport_active)
7310                         R_TimeReport("modeldepth");
7311         }
7312
7313         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7314         {
7315                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7316                 if (r_timereport_active)
7317                         R_TimeReport("world");
7318         }
7319
7320         // don't let sound skip if going slow
7321         if (r_refdef.scene.extraupdate)
7322                 S_ExtraUpdate ();
7323
7324         R_DrawModels();
7325         if (r_timereport_active)
7326                 R_TimeReport("models");
7327
7328         // don't let sound skip if going slow
7329         if (r_refdef.scene.extraupdate)
7330                 S_ExtraUpdate ();
7331
7332         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7333         {
7334                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7335                 R_Shadow_DrawModelShadows();
7336                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7337                 // don't let sound skip if going slow
7338                 if (r_refdef.scene.extraupdate)
7339                         S_ExtraUpdate ();
7340         }
7341
7342         if (!r_shadow_usingdeferredprepass)
7343         {
7344                 R_Shadow_DrawLights();
7345                 if (r_timereport_active)
7346                         R_TimeReport("rtlights");
7347         }
7348
7349         // don't let sound skip if going slow
7350         if (r_refdef.scene.extraupdate)
7351                 S_ExtraUpdate ();
7352
7353         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7354         {
7355                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7356                 R_Shadow_DrawModelShadows();
7357                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7358                 // don't let sound skip if going slow
7359                 if (r_refdef.scene.extraupdate)
7360                         S_ExtraUpdate ();
7361         }
7362
7363         if (cl.csqc_vidvars.drawworld)
7364         {
7365                 if (cl_decals_newsystem.integer)
7366                 {
7367                         R_DrawModelDecals();
7368                         if (r_timereport_active)
7369                                 R_TimeReport("modeldecals");
7370                 }
7371                 else
7372                 {
7373                         R_DrawDecals();
7374                         if (r_timereport_active)
7375                                 R_TimeReport("decals");
7376                 }
7377
7378                 R_DrawParticles();
7379                 if (r_timereport_active)
7380                         R_TimeReport("particles");
7381
7382                 R_DrawExplosions();
7383                 if (r_timereport_active)
7384                         R_TimeReport("explosions");
7385         }
7386
7387         if (cl.csqc_loaded)
7388                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7389
7390         if (r_refdef.view.showdebug)
7391         {
7392                 if (cl_locs_show.integer)
7393                 {
7394                         R_DrawLocs();
7395                         if (r_timereport_active)
7396                                 R_TimeReport("showlocs");
7397                 }
7398
7399                 if (r_drawportals.integer)
7400                 {
7401                         R_DrawPortals();
7402                         if (r_timereport_active)
7403                                 R_TimeReport("portals");
7404                 }
7405
7406                 if (r_showbboxes_client.value > 0)
7407                 {
7408                         R_DrawEntityBBoxes(CLVM_prog);
7409                         if (r_timereport_active)
7410                                 R_TimeReport("clbboxes");
7411                 }
7412                 if (r_showbboxes.value > 0)
7413                 {
7414                         R_DrawEntityBBoxes(SVVM_prog);
7415                         if (r_timereport_active)
7416                                 R_TimeReport("svbboxes");
7417                 }
7418         }
7419
7420         if (r_transparent.integer)
7421         {
7422                 R_MeshQueue_RenderTransparent();
7423                 if (r_timereport_active)
7424                         R_TimeReport("drawtrans");
7425         }
7426
7427         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7428         {
7429                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7430                 if (r_timereport_active)
7431                         R_TimeReport("worlddebug");
7432                 R_DrawModelsDebug();
7433                 if (r_timereport_active)
7434                         R_TimeReport("modeldebug");
7435         }
7436
7437         if (cl.csqc_vidvars.drawworld)
7438         {
7439                 R_Shadow_DrawCoronas();
7440                 if (r_timereport_active)
7441                         R_TimeReport("coronas");
7442         }
7443
7444 #if 0
7445         {
7446                 GL_DepthTest(false);
7447                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7448                 GL_Color(1, 1, 1, 1);
7449                 qglBegin(GL_POLYGON);
7450                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7451                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7452                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7453                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7454                 qglEnd();
7455                 qglBegin(GL_POLYGON);
7456                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7457                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7458                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7459                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7460                 qglEnd();
7461                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7462         }
7463 #endif
7464
7465         // don't let sound skip if going slow
7466         if (r_refdef.scene.extraupdate)
7467                 S_ExtraUpdate ();
7468 }
7469
7470 static const unsigned short bboxelements[36] =
7471 {
7472         5, 1, 3, 5, 3, 7,
7473         6, 2, 0, 6, 0, 4,
7474         7, 3, 2, 7, 2, 6,
7475         4, 0, 1, 4, 1, 5,
7476         4, 5, 7, 4, 7, 6,
7477         1, 0, 2, 1, 2, 3,
7478 };
7479
7480 #define BBOXEDGES 13
7481 static const float bboxedges[BBOXEDGES][6] = 
7482 {
7483         // whole box
7484         { 0, 0, 0, 1, 1, 1 },
7485         // bottom edges
7486         { 0, 0, 0, 0, 1, 0 },
7487         { 0, 0, 0, 1, 0, 0 },
7488         { 0, 1, 0, 1, 1, 0 },
7489         { 1, 0, 0, 1, 1, 0 },
7490         // top edges
7491         { 0, 0, 1, 0, 1, 1 },
7492         { 0, 0, 1, 1, 0, 1 },
7493         { 0, 1, 1, 1, 1, 1 },
7494         { 1, 0, 1, 1, 1, 1 },
7495         // vertical edges
7496         { 0, 0, 0, 0, 0, 1 },
7497         { 1, 0, 0, 1, 0, 1 },
7498         { 0, 1, 0, 0, 1, 1 },
7499         { 1, 1, 0, 1, 1, 1 },
7500 };
7501
7502 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7503 {
7504         int numvertices = BBOXEDGES * 8;
7505         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7506         int numtriangles = BBOXEDGES * 12;
7507         unsigned short elements[BBOXEDGES * 36];
7508         int i, edge;
7509         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7510
7511         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7512
7513         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7514         GL_DepthMask(false);
7515         GL_DepthRange(0, 1);
7516         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7517
7518         for (edge = 0; edge < BBOXEDGES; edge++)
7519         {
7520                 for (i = 0; i < 3; i++)
7521                 {
7522                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7523                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7524                 }
7525                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7526                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7527                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7528                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7529                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7530                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7531                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7532                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7533                 for (i = 0; i < 36; i++)
7534                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7535         }
7536         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7537         if (r_refdef.fogenabled)
7538         {
7539                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7540                 {
7541                         f1 = RSurf_FogVertex(v);
7542                         f2 = 1 - f1;
7543                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7544                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7545                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7546                 }
7547         }
7548         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7549         R_Mesh_ResetTextureState();
7550         R_SetupShader_Generic_NoTexture(false, false);
7551         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7552 }
7553
7554 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7555 {
7556         // hacky overloading of the parameters
7557         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7558         int i;
7559         float color[4];
7560         prvm_edict_t *edict;
7561
7562         GL_CullFace(GL_NONE);
7563         R_SetupShader_Generic_NoTexture(false, false);
7564
7565         for (i = 0;i < numsurfaces;i++)
7566         {
7567                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7568                 switch ((int)PRVM_serveredictfloat(edict, solid))
7569                 {
7570                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7571                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7572                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7573                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7574                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7575                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7576                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7577                 }
7578                 if (prog == CLVM_prog)
7579                         color[3] *= r_showbboxes_client.value;
7580                 else
7581                         color[3] *= r_showbboxes.value;
7582                 color[3] = bound(0, color[3], 1);
7583                 GL_DepthTest(!r_showdisabledepthtest.integer);
7584                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7585         }
7586 }
7587
7588 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7589 {
7590         int i;
7591         prvm_edict_t *edict;
7592         vec3_t center;
7593
7594         if (prog == NULL)
7595                 return;
7596
7597         for (i = 0; i < prog->num_edicts; i++)
7598         {
7599                 edict = PRVM_EDICT_NUM(i);
7600                 if (edict->priv.server->free)
7601                         continue;
7602                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7603                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7604                         continue;
7605                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7606                         continue;
7607                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7608                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7609         }
7610 }
7611
7612 static const int nomodelelement3i[24] =
7613 {
7614         5, 2, 0,
7615         5, 1, 2,
7616         5, 0, 3,
7617         5, 3, 1,
7618         0, 2, 4,
7619         2, 1, 4,
7620         3, 0, 4,
7621         1, 3, 4
7622 };
7623
7624 static const unsigned short nomodelelement3s[24] =
7625 {
7626         5, 2, 0,
7627         5, 1, 2,
7628         5, 0, 3,
7629         5, 3, 1,
7630         0, 2, 4,
7631         2, 1, 4,
7632         3, 0, 4,
7633         1, 3, 4
7634 };
7635
7636 static const float nomodelvertex3f[6*3] =
7637 {
7638         -16,   0,   0,
7639          16,   0,   0,
7640           0, -16,   0,
7641           0,  16,   0,
7642           0,   0, -16,
7643           0,   0,  16
7644 };
7645
7646 static const float nomodelcolor4f[6*4] =
7647 {
7648         0.0f, 0.0f, 0.5f, 1.0f,
7649         0.0f, 0.0f, 0.5f, 1.0f,
7650         0.0f, 0.5f, 0.0f, 1.0f,
7651         0.0f, 0.5f, 0.0f, 1.0f,
7652         0.5f, 0.0f, 0.0f, 1.0f,
7653         0.5f, 0.0f, 0.0f, 1.0f
7654 };
7655
7656 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7657 {
7658         int i;
7659         float f1, f2, *c;
7660         float color4f[6*4];
7661
7662         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7663
7664         // this is only called once per entity so numsurfaces is always 1, and
7665         // surfacelist is always {0}, so this code does not handle batches
7666
7667         if (rsurface.ent_flags & RENDER_ADDITIVE)
7668         {
7669                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7670                 GL_DepthMask(false);
7671         }
7672         else if (ent->alpha < 1)
7673         {
7674                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7675                 GL_DepthMask(false);
7676         }
7677         else
7678         {
7679                 GL_BlendFunc(GL_ONE, GL_ZERO);
7680                 GL_DepthMask(true);
7681         }
7682         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7683         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7684         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7685         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7686         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7687         for (i = 0, c = color4f;i < 6;i++, c += 4)
7688         {
7689                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7690                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7691                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7692                 c[3] *= ent->alpha;
7693         }
7694         if (r_refdef.fogenabled)
7695         {
7696                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7697                 {
7698                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7699                         f2 = 1 - f1;
7700                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7701                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7702                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7703                 }
7704         }
7705 //      R_Mesh_ResetTextureState();
7706         R_SetupShader_Generic_NoTexture(false, false);
7707         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7708         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7709 }
7710
7711 void R_DrawNoModel(entity_render_t *ent)
7712 {
7713         vec3_t org;
7714         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7715         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7716                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7717         else
7718                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7719 }
7720
7721 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7722 {
7723         vec3_t right1, right2, diff, normal;
7724
7725         VectorSubtract (org2, org1, normal);
7726
7727         // calculate 'right' vector for start
7728         VectorSubtract (r_refdef.view.origin, org1, diff);
7729         CrossProduct (normal, diff, right1);
7730         VectorNormalize (right1);
7731
7732         // calculate 'right' vector for end
7733         VectorSubtract (r_refdef.view.origin, org2, diff);
7734         CrossProduct (normal, diff, right2);
7735         VectorNormalize (right2);
7736
7737         vert[ 0] = org1[0] + width * right1[0];
7738         vert[ 1] = org1[1] + width * right1[1];
7739         vert[ 2] = org1[2] + width * right1[2];
7740         vert[ 3] = org1[0] - width * right1[0];
7741         vert[ 4] = org1[1] - width * right1[1];
7742         vert[ 5] = org1[2] - width * right1[2];
7743         vert[ 6] = org2[0] - width * right2[0];
7744         vert[ 7] = org2[1] - width * right2[1];
7745         vert[ 8] = org2[2] - width * right2[2];
7746         vert[ 9] = org2[0] + width * right2[0];
7747         vert[10] = org2[1] + width * right2[1];
7748         vert[11] = org2[2] + width * right2[2];
7749 }
7750
7751 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7752 {
7753         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7754         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7755         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7756         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7757         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7758         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7759         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7760         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7761         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7762         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7763         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7764         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7765 }
7766
7767 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7768 {
7769         int i;
7770         float *vertex3f;
7771         float v[3];
7772         VectorSet(v, x, y, z);
7773         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7774                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7775                         break;
7776         if (i == mesh->numvertices)
7777         {
7778                 if (mesh->numvertices < mesh->maxvertices)
7779                 {
7780                         VectorCopy(v, vertex3f);
7781                         mesh->numvertices++;
7782                 }
7783                 return mesh->numvertices;
7784         }
7785         else
7786                 return i;
7787 }
7788
7789 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7790 {
7791         int i;
7792         int *e, element[3];
7793         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7794         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7795         e = mesh->element3i + mesh->numtriangles * 3;
7796         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7797         {
7798                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7799                 if (mesh->numtriangles < mesh->maxtriangles)
7800                 {
7801                         *e++ = element[0];
7802                         *e++ = element[1];
7803                         *e++ = element[2];
7804                         mesh->numtriangles++;
7805                 }
7806                 element[1] = element[2];
7807         }
7808 }
7809
7810 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7811 {
7812         int i;
7813         int *e, element[3];
7814         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7815         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7816         e = mesh->element3i + mesh->numtriangles * 3;
7817         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7818         {
7819                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7820                 if (mesh->numtriangles < mesh->maxtriangles)
7821                 {
7822                         *e++ = element[0];
7823                         *e++ = element[1];
7824                         *e++ = element[2];
7825                         mesh->numtriangles++;
7826                 }
7827                 element[1] = element[2];
7828         }
7829 }
7830
7831 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7832 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7833 {
7834         int planenum, planenum2;
7835         int w;
7836         int tempnumpoints;
7837         mplane_t *plane, *plane2;
7838         double maxdist;
7839         double temppoints[2][256*3];
7840         // figure out how large a bounding box we need to properly compute this brush
7841         maxdist = 0;
7842         for (w = 0;w < numplanes;w++)
7843                 maxdist = max(maxdist, fabs(planes[w].dist));
7844         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7845         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7846         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7847         {
7848                 w = 0;
7849                 tempnumpoints = 4;
7850                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7851                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7852                 {
7853                         if (planenum2 == planenum)
7854                                 continue;
7855                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7856                         w = !w;
7857                 }
7858                 if (tempnumpoints < 3)
7859                         continue;
7860                 // generate elements forming a triangle fan for this polygon
7861                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7862         }
7863 }
7864
7865 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7866 {
7867         texturelayer_t *layer;
7868         layer = t->currentlayers + t->currentnumlayers++;
7869         layer->type = type;
7870         layer->depthmask = depthmask;
7871         layer->blendfunc1 = blendfunc1;
7872         layer->blendfunc2 = blendfunc2;
7873         layer->texture = texture;
7874         layer->texmatrix = *matrix;
7875         layer->color[0] = r;
7876         layer->color[1] = g;
7877         layer->color[2] = b;
7878         layer->color[3] = a;
7879 }
7880
7881 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7882 {
7883         if(parms[0] == 0 && parms[1] == 0)
7884                 return false;
7885         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7886                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7887                         return false;
7888         return true;
7889 }
7890
7891 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7892 {
7893         double index, f;
7894         index = parms[2] + rsurface.shadertime * parms[3];
7895         index -= floor(index);
7896         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7897         {
7898         default:
7899         case Q3WAVEFUNC_NONE:
7900         case Q3WAVEFUNC_NOISE:
7901         case Q3WAVEFUNC_COUNT:
7902                 f = 0;
7903                 break;
7904         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7905         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7906         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7907         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7908         case Q3WAVEFUNC_TRIANGLE:
7909                 index *= 4;
7910                 f = index - floor(index);
7911                 if (index < 1)
7912                 {
7913                         // f = f;
7914                 }
7915                 else if (index < 2)
7916                         f = 1 - f;
7917                 else if (index < 3)
7918                         f = -f;
7919                 else
7920                         f = -(1 - f);
7921                 break;
7922         }
7923         f = parms[0] + parms[1] * f;
7924         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7925                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7926         return (float) f;
7927 }
7928
7929 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7930 {
7931         int w, h, idx;
7932         float shadertime;
7933         float f;
7934         float offsetd[2];
7935         float tcmat[12];
7936         matrix4x4_t matrix, temp;
7937         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7938         // it's better to have one huge fixup every 9 hours than gradual
7939         // degradation over time which looks consistently bad after many hours.
7940         //
7941         // tcmod scroll in particular suffers from this degradation which can't be
7942         // effectively worked around even with floor() tricks because we don't
7943         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7944         // a workaround involving floor() would be incorrect anyway...
7945         shadertime = rsurface.shadertime;
7946         if (shadertime >= 32768.0f)
7947                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7948         switch(tcmod->tcmod)
7949         {
7950                 case Q3TCMOD_COUNT:
7951                 case Q3TCMOD_NONE:
7952                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7953                                 matrix = r_waterscrollmatrix;
7954                         else
7955                                 matrix = identitymatrix;
7956                         break;
7957                 case Q3TCMOD_ENTITYTRANSLATE:
7958                         // this is used in Q3 to allow the gamecode to control texcoord
7959                         // scrolling on the entity, which is not supported in darkplaces yet.
7960                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7961                         break;
7962                 case Q3TCMOD_ROTATE:
7963                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7964                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7965                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7966                         break;
7967                 case Q3TCMOD_SCALE:
7968                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7969                         break;
7970                 case Q3TCMOD_SCROLL:
7971                         // this particular tcmod is a "bug for bug" compatible one with regards to
7972                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7973                         // specifically did the wrapping and so we must mimic that...
7974                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7975                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7976                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7977                         break;
7978                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7979                         w = (int) tcmod->parms[0];
7980                         h = (int) tcmod->parms[1];
7981                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7982                         f = f - floor(f);
7983                         idx = (int) floor(f * w * h);
7984                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7985                         break;
7986                 case Q3TCMOD_STRETCH:
7987                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7988                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7989                         break;
7990                 case Q3TCMOD_TRANSFORM:
7991                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7992                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7993                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7994                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7995                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7996                         break;
7997                 case Q3TCMOD_TURBULENT:
7998                         // this is handled in the RSurf_PrepareVertices function
7999                         matrix = identitymatrix;
8000                         break;
8001         }
8002         temp = *texmatrix;
8003         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8004 }
8005
8006 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8007 {
8008         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8009         char name[MAX_QPATH];
8010         skinframe_t *skinframe;
8011         unsigned char pixels[296*194];
8012         strlcpy(cache->name, skinname, sizeof(cache->name));
8013         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8014         if (developer_loading.integer)
8015                 Con_Printf("loading %s\n", name);
8016         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8017         if (!skinframe || !skinframe->base)
8018         {
8019                 unsigned char *f;
8020                 fs_offset_t filesize;
8021                 skinframe = NULL;
8022                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8023                 if (f)
8024                 {
8025                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8026                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8027                         Mem_Free(f);
8028                 }
8029         }
8030         cache->skinframe = skinframe;
8031 }
8032
8033 texture_t *R_GetCurrentTexture(texture_t *t)
8034 {
8035         int i, q;
8036         const entity_render_t *ent = rsurface.entity;
8037         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8038         q3shaderinfo_layer_tcmod_t *tcmod;
8039         float specularscale = 0.0f;
8040
8041         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8042                 return t->currentframe;
8043         t->update_lastrenderframe = r_textureframe;
8044         t->update_lastrenderentity = (void *)ent;
8045
8046         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8047                 t->camera_entity = ent->entitynumber;
8048         else
8049                 t->camera_entity = 0;
8050
8051         // switch to an alternate material if this is a q1bsp animated material
8052         {
8053                 texture_t *texture = t;
8054                 int s = rsurface.ent_skinnum;
8055                 if ((unsigned int)s >= (unsigned int)model->numskins)
8056                         s = 0;
8057                 if (model->skinscenes)
8058                 {
8059                         if (model->skinscenes[s].framecount > 1)
8060                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8061                         else
8062                                 s = model->skinscenes[s].firstframe;
8063                 }
8064                 if (s > 0)
8065                         t = t + s * model->num_surfaces;
8066                 if (t->animated)
8067                 {
8068                         // use an alternate animation if the entity's frame is not 0,
8069                         // and only if the texture has an alternate animation
8070                         if (t->animated == 2) // q2bsp
8071                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8072                         else if (rsurface.ent_alttextures && t->anim_total[1])
8073                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8074                         else
8075                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8076                 }
8077                 texture->currentframe = t;
8078         }
8079
8080         // update currentskinframe to be a qw skin or animation frame
8081         if (rsurface.ent_qwskin >= 0)
8082         {
8083                 i = rsurface.ent_qwskin;
8084                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8085                 {
8086                         r_qwskincache_size = cl.maxclients;
8087                         if (r_qwskincache)
8088                                 Mem_Free(r_qwskincache);
8089                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8090                 }
8091                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8092                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8093                 t->currentskinframe = r_qwskincache[i].skinframe;
8094                 if (t->materialshaderpass && t->currentskinframe == NULL)
8095                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8096         }
8097         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8098                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8099         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8100                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8101
8102         t->currentmaterialflags = t->basematerialflags;
8103         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8104         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8105                 t->currentalpha *= r_wateralpha.value;
8106         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8107                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8108         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8109                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8110
8111         // decide on which type of lighting to use for this surface
8112         if (rsurface.entity->render_modellight_forced)
8113                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8114         if (rsurface.entity->render_rtlight_disabled)
8115                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8116         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8117         {
8118                 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8119                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8120                 for (q = 0; q < 3; q++)
8121                 {
8122                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8123                         t->render_modellight_lightdir[q] = q == 2;
8124                         t->render_modellight_ambient[q] = 1;
8125                         t->render_modellight_diffuse[q] = 0;
8126                         t->render_modellight_specular[q] = 0;
8127                         t->render_lightmap_ambient[q] = 0;
8128                         t->render_lightmap_diffuse[q] = 0;
8129                         t->render_lightmap_specular[q] = 0;
8130                         t->render_rtlight_diffuse[q] = 0;
8131                         t->render_rtlight_specular[q] = 0;
8132                 }
8133         }
8134         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8135         {
8136                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8137                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8138                 for (q = 0; q < 3; q++)
8139                 {
8140                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8141                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8142                         t->render_modellight_lightdir[q] = q == 2;
8143                         t->render_modellight_diffuse[q] = 0;
8144                         t->render_modellight_specular[q] = 0;
8145                         t->render_lightmap_ambient[q] = 0;
8146                         t->render_lightmap_diffuse[q] = 0;
8147                         t->render_lightmap_specular[q] = 0;
8148                         t->render_rtlight_diffuse[q] = 0;
8149                         t->render_rtlight_specular[q] = 0;
8150                 }
8151         }
8152         else if (FAKELIGHT_ENABLED)
8153         {
8154                 // no modellight if using fakelight for the map
8155                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8156                 for (q = 0; q < 3; q++)
8157                 {
8158                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8159                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8160                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8161                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8162                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8163                         t->render_lightmap_ambient[q] = 0;
8164                         t->render_lightmap_diffuse[q] = 0;
8165                         t->render_lightmap_specular[q] = 0;
8166                         t->render_rtlight_diffuse[q] = 0;
8167                         t->render_rtlight_specular[q] = 0;
8168                 }
8169         }
8170         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8171         {
8172                 // ambient + single direction light (modellight)
8173                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8174                 for (q = 0; q < 3; q++)
8175                 {
8176                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8177                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8178                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8179                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8180                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8181                         t->render_lightmap_ambient[q] = 0;
8182                         t->render_lightmap_diffuse[q] = 0;
8183                         t->render_lightmap_specular[q] = 0;
8184                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8185                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8186                 }
8187         }
8188         else
8189         {
8190                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8191                 for (q = 0; q < 3; q++)
8192                 {
8193                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8194                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8195                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8196                         t->render_modellight_diffuse[q] = 0;
8197                         t->render_modellight_specular[q] = 0;
8198                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8199                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8200                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8201                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8202                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8203                 }
8204         }
8205
8206         for (q = 0; q < 3; q++)
8207         {
8208                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8209                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8210         }
8211
8212         if (rsurface.ent_flags & RENDER_ADDITIVE)
8213                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8214         else if (t->currentalpha < 1)
8215                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8216         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8217         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8218                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8219         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8220                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8221         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8222                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8223         if (t->backgroundshaderpass)
8224                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8225         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8226         {
8227                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8228                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8229         }
8230         else
8231                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8232         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8233         {
8234                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8235                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8236         }
8237         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8238                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8239
8240         // there is no tcmod
8241         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8242         {
8243                 t->currenttexmatrix = r_waterscrollmatrix;
8244                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8245         }
8246         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8247         {
8248                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8249                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8250         }
8251
8252         if (t->materialshaderpass)
8253                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8254                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8255
8256         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8257         if (t->currentskinframe->qpixels)
8258                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8259         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8260         if (!t->basetexture)
8261                 t->basetexture = r_texture_notexture;
8262         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8263         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8264         t->nmaptexture = t->currentskinframe->nmap;
8265         if (!t->nmaptexture)
8266                 t->nmaptexture = r_texture_blanknormalmap;
8267         t->glosstexture = r_texture_black;
8268         t->glowtexture = t->currentskinframe->glow;
8269         t->fogtexture = t->currentskinframe->fog;
8270         t->reflectmasktexture = t->currentskinframe->reflect;
8271         if (t->backgroundshaderpass)
8272         {
8273                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8274                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8275                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8276                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8277                 t->backgroundglosstexture = r_texture_black;
8278                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8279                 if (!t->backgroundnmaptexture)
8280                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8281                 // make sure that if glow is going to be used, both textures are not NULL
8282                 if (!t->backgroundglowtexture && t->glowtexture)
8283                         t->backgroundglowtexture = r_texture_black;
8284                 if (!t->glowtexture && t->backgroundglowtexture)
8285                         t->glowtexture = r_texture_black;
8286         }
8287         else
8288         {
8289                 t->backgroundbasetexture = r_texture_white;
8290                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8291                 t->backgroundglosstexture = r_texture_black;
8292                 t->backgroundglowtexture = NULL;
8293         }
8294         t->specularpower = r_shadow_glossexponent.value;
8295         // TODO: store reference values for these in the texture?
8296         if (r_shadow_gloss.integer > 0)
8297         {
8298                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8299                 {
8300                         if (r_shadow_glossintensity.value > 0)
8301                         {
8302                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8303                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8304                                 specularscale = r_shadow_glossintensity.value;
8305                         }
8306                 }
8307                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8308                 {
8309                         t->glosstexture = r_texture_white;
8310                         t->backgroundglosstexture = r_texture_white;
8311                         specularscale = r_shadow_gloss2intensity.value;
8312                         t->specularpower = r_shadow_gloss2exponent.value;
8313                 }
8314         }
8315         specularscale *= t->specularscalemod;
8316         t->specularpower *= t->specularpowermod;
8317
8318         // lightmaps mode looks bad with dlights using actual texturing, so turn
8319         // off the colormap and glossmap, but leave the normalmap on as it still
8320         // accurately represents the shading involved
8321         if (gl_lightmaps.integer)
8322         {
8323                 t->basetexture = r_texture_grey128;
8324                 t->pantstexture = r_texture_black;
8325                 t->shirttexture = r_texture_black;
8326                 if (gl_lightmaps.integer < 2)
8327                         t->nmaptexture = r_texture_blanknormalmap;
8328                 t->glosstexture = r_texture_black;
8329                 t->glowtexture = NULL;
8330                 t->fogtexture = NULL;
8331                 t->reflectmasktexture = NULL;
8332                 t->backgroundbasetexture = NULL;
8333                 if (gl_lightmaps.integer < 2)
8334                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8335                 t->backgroundglosstexture = r_texture_black;
8336                 t->backgroundglowtexture = NULL;
8337                 specularscale = 0;
8338                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8339         }
8340
8341         if (specularscale != 1.0f)
8342         {
8343                 for (q = 0; q < 3; q++)
8344                 {
8345                         t->render_modellight_specular[q] *= specularscale;
8346                         t->render_lightmap_specular[q] *= specularscale;
8347                         t->render_rtlight_specular[q] *= specularscale;
8348                 }
8349         }
8350
8351         t->currentnumlayers = 0;
8352         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8353         {
8354                 int blendfunc1, blendfunc2;
8355                 qboolean depthmask;
8356                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8357                 {
8358                         blendfunc1 = GL_SRC_ALPHA;
8359                         blendfunc2 = GL_ONE;
8360                 }
8361                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8362                 {
8363                         blendfunc1 = GL_SRC_ALPHA;
8364                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8365                 }
8366                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8367                 {
8368                         blendfunc1 = t->customblendfunc[0];
8369                         blendfunc2 = t->customblendfunc[1];
8370                 }
8371                 else
8372                 {
8373                         blendfunc1 = GL_ONE;
8374                         blendfunc2 = GL_ZERO;
8375                 }
8376                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8377                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8378                 {
8379                         // basic lit geometry
8380                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8381                         // add pants/shirt if needed
8382                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8383                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8384                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8385                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8386                 }
8387                 else
8388                 {
8389                         // basic lit geometry
8390                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8391                         // add pants/shirt if needed
8392                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8393                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8394                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8395                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8396                         // now add ambient passes if needed
8397                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8398                         {
8399                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8400                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8401                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8402                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8403                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8404                         }
8405                 }
8406                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8407                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8408                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8409                 {
8410                         // if this is opaque use alpha blend which will darken the earlier
8411                         // passes cheaply.
8412                         //
8413                         // if this is an alpha blended material, all the earlier passes
8414                         // were darkened by fog already, so we only need to add the fog
8415                         // color ontop through the fog mask texture
8416                         //
8417                         // if this is an additive blended material, all the earlier passes
8418                         // were darkened by fog already, and we should not add fog color
8419                         // (because the background was not darkened, there is no fog color
8420                         // that was lost behind it).
8421                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8422                 }
8423         }
8424
8425         return t;
8426 }
8427
8428 rsurfacestate_t rsurface;
8429
8430 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8431 {
8432         dp_model_t *model = ent->model;
8433         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8434         //      return;
8435         rsurface.entity = (entity_render_t *)ent;
8436         rsurface.skeleton = ent->skeleton;
8437         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8438         rsurface.ent_skinnum = ent->skinnum;
8439         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8440         rsurface.ent_flags = ent->flags;
8441         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8442                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8443         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8444         rsurface.matrix = ent->matrix;
8445         rsurface.inversematrix = ent->inversematrix;
8446         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8447         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8448         R_EntityMatrix(&rsurface.matrix);
8449         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8450         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8451         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8452         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8453         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8454         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8455         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8456         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8457         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8458         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8459         if (ent->model->brush.submodel && !prepass)
8460         {
8461                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8462                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8463         }
8464         // if the animcache code decided it should use the shader path, skip the deform step
8465         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8466         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8467         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8468         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8469         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8470         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8471         {
8472                 if (ent->animcache_vertex3f)
8473                 {
8474                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8475                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8476                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8477                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8478                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8479                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8480                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8481                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8482                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8483                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8484                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8485                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8486                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8487                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8488                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8489                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8490                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8491                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8492                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8493                 }
8494                 else if (wanttangents)
8495                 {
8496                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8497                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8498                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8499                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8500                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8501                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8502                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8503                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8504                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8505                         rsurface.modelvertexmesh = NULL;
8506                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8507                         rsurface.modelvertexmesh_bufferoffset = 0;
8508                         rsurface.modelvertex3f_vertexbuffer = NULL;
8509                         rsurface.modelvertex3f_bufferoffset = 0;
8510                         rsurface.modelvertex3f_vertexbuffer = 0;
8511                         rsurface.modelvertex3f_bufferoffset = 0;
8512                         rsurface.modelsvector3f_vertexbuffer = 0;
8513                         rsurface.modelsvector3f_bufferoffset = 0;
8514                         rsurface.modeltvector3f_vertexbuffer = 0;
8515                         rsurface.modeltvector3f_bufferoffset = 0;
8516                         rsurface.modelnormal3f_vertexbuffer = 0;
8517                         rsurface.modelnormal3f_bufferoffset = 0;
8518                 }
8519                 else if (wantnormals)
8520                 {
8521                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8522                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8523                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8524                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8525                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8526                         rsurface.modelsvector3f = NULL;
8527                         rsurface.modeltvector3f = NULL;
8528                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8529                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8530                         rsurface.modelvertexmesh = NULL;
8531                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8532                         rsurface.modelvertexmesh_bufferoffset = 0;
8533                         rsurface.modelvertex3f_vertexbuffer = NULL;
8534                         rsurface.modelvertex3f_bufferoffset = 0;
8535                         rsurface.modelvertex3f_vertexbuffer = 0;
8536                         rsurface.modelvertex3f_bufferoffset = 0;
8537                         rsurface.modelsvector3f_vertexbuffer = 0;
8538                         rsurface.modelsvector3f_bufferoffset = 0;
8539                         rsurface.modeltvector3f_vertexbuffer = 0;
8540                         rsurface.modeltvector3f_bufferoffset = 0;
8541                         rsurface.modelnormal3f_vertexbuffer = 0;
8542                         rsurface.modelnormal3f_bufferoffset = 0;
8543                 }
8544                 else
8545                 {
8546                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8547                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8548                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8549                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8550                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8551                         rsurface.modelsvector3f = NULL;
8552                         rsurface.modeltvector3f = NULL;
8553                         rsurface.modelnormal3f = NULL;
8554                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8555                         rsurface.modelvertexmesh = NULL;
8556                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8557                         rsurface.modelvertexmesh_bufferoffset = 0;
8558                         rsurface.modelvertex3f_vertexbuffer = NULL;
8559                         rsurface.modelvertex3f_bufferoffset = 0;
8560                         rsurface.modelvertex3f_vertexbuffer = 0;
8561                         rsurface.modelvertex3f_bufferoffset = 0;
8562                         rsurface.modelsvector3f_vertexbuffer = 0;
8563                         rsurface.modelsvector3f_bufferoffset = 0;
8564                         rsurface.modeltvector3f_vertexbuffer = 0;
8565                         rsurface.modeltvector3f_bufferoffset = 0;
8566                         rsurface.modelnormal3f_vertexbuffer = 0;
8567                         rsurface.modelnormal3f_bufferoffset = 0;
8568                 }
8569                 rsurface.modelgeneratedvertex = true;
8570         }
8571         else
8572         {
8573                 if (rsurface.entityskeletaltransform3x4)
8574                 {
8575                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8576                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8577                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8578                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8579                 }
8580                 else
8581                 {
8582                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8583                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8584                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8585                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8586                 }
8587                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8588                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8589                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8590                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8591                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8592                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8593                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8594                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8595                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8596                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8597                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8598                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8599                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8600                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8601                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8602                 rsurface.modelgeneratedvertex = false;
8603         }
8604         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8605         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8606         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8607         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8608         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8609         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8610         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8611         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8612         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8613         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8614         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8615         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8616         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8617         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8618         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8619         rsurface.modelelement3i = model->surfmesh.data_element3i;
8620         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8621         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8622         rsurface.modelelement3s = model->surfmesh.data_element3s;
8623         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8624         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8625         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8626         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8627         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8628         rsurface.modelsurfaces = model->data_surfaces;
8629         rsurface.batchgeneratedvertex = false;
8630         rsurface.batchfirstvertex = 0;
8631         rsurface.batchnumvertices = 0;
8632         rsurface.batchfirsttriangle = 0;
8633         rsurface.batchnumtriangles = 0;
8634         rsurface.batchvertex3f  = NULL;
8635         rsurface.batchvertex3f_vertexbuffer = NULL;
8636         rsurface.batchvertex3f_bufferoffset = 0;
8637         rsurface.batchsvector3f = NULL;
8638         rsurface.batchsvector3f_vertexbuffer = NULL;
8639         rsurface.batchsvector3f_bufferoffset = 0;
8640         rsurface.batchtvector3f = NULL;
8641         rsurface.batchtvector3f_vertexbuffer = NULL;
8642         rsurface.batchtvector3f_bufferoffset = 0;
8643         rsurface.batchnormal3f  = NULL;
8644         rsurface.batchnormal3f_vertexbuffer = NULL;
8645         rsurface.batchnormal3f_bufferoffset = 0;
8646         rsurface.batchlightmapcolor4f = NULL;
8647         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8648         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8649         rsurface.batchtexcoordtexture2f = NULL;
8650         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8651         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8652         rsurface.batchtexcoordlightmap2f = NULL;
8653         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8654         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8655         rsurface.batchskeletalindex4ub = NULL;
8656         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8657         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8658         rsurface.batchskeletalweight4ub = NULL;
8659         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8660         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8661         rsurface.batchvertexmesh = NULL;
8662         rsurface.batchvertexmesh_vertexbuffer = NULL;
8663         rsurface.batchvertexmesh_bufferoffset = 0;
8664         rsurface.batchelement3i = NULL;
8665         rsurface.batchelement3i_indexbuffer = NULL;
8666         rsurface.batchelement3i_bufferoffset = 0;
8667         rsurface.batchelement3s = NULL;
8668         rsurface.batchelement3s_indexbuffer = NULL;
8669         rsurface.batchelement3s_bufferoffset = 0;
8670         rsurface.passcolor4f = NULL;
8671         rsurface.passcolor4f_vertexbuffer = NULL;
8672         rsurface.passcolor4f_bufferoffset = 0;
8673         rsurface.forcecurrenttextureupdate = false;
8674 }
8675
8676 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8677 {
8678         rsurface.entity = r_refdef.scene.worldentity;
8679         rsurface.skeleton = NULL;
8680         rsurface.ent_skinnum = 0;
8681         rsurface.ent_qwskin = -1;
8682         rsurface.ent_flags = entflags;
8683         rsurface.shadertime = r_refdef.scene.time - shadertime;
8684         rsurface.modelnumvertices = numvertices;
8685         rsurface.modelnumtriangles = numtriangles;
8686         rsurface.matrix = *matrix;
8687         rsurface.inversematrix = *inversematrix;
8688         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8689         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8690         R_EntityMatrix(&rsurface.matrix);
8691         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8692         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8693         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8694         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8695         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8696         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8697         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8698         rsurface.frameblend[0].lerp = 1;
8699         rsurface.ent_alttextures = false;
8700         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8701         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8702         rsurface.entityskeletaltransform3x4 = NULL;
8703         rsurface.entityskeletaltransform3x4buffer = NULL;
8704         rsurface.entityskeletaltransform3x4offset = 0;
8705         rsurface.entityskeletaltransform3x4size = 0;
8706         rsurface.entityskeletalnumtransforms = 0;
8707         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8708         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8709         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8710         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8711         if (wanttangents)
8712         {
8713                 rsurface.modelvertex3f = (float *)vertex3f;
8714                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8715                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8716                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8717         }
8718         else if (wantnormals)
8719         {
8720                 rsurface.modelvertex3f = (float *)vertex3f;
8721                 rsurface.modelsvector3f = NULL;
8722                 rsurface.modeltvector3f = NULL;
8723                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8724         }
8725         else
8726         {
8727                 rsurface.modelvertex3f = (float *)vertex3f;
8728                 rsurface.modelsvector3f = NULL;
8729                 rsurface.modeltvector3f = NULL;
8730                 rsurface.modelnormal3f = NULL;
8731         }
8732         rsurface.modelvertexmesh = NULL;
8733         rsurface.modelvertexmesh_vertexbuffer = NULL;
8734         rsurface.modelvertexmesh_bufferoffset = 0;
8735         rsurface.modelvertex3f_vertexbuffer = 0;
8736         rsurface.modelvertex3f_bufferoffset = 0;
8737         rsurface.modelsvector3f_vertexbuffer = 0;
8738         rsurface.modelsvector3f_bufferoffset = 0;
8739         rsurface.modeltvector3f_vertexbuffer = 0;
8740         rsurface.modeltvector3f_bufferoffset = 0;
8741         rsurface.modelnormal3f_vertexbuffer = 0;
8742         rsurface.modelnormal3f_bufferoffset = 0;
8743         rsurface.modelgeneratedvertex = true;
8744         rsurface.modellightmapcolor4f  = (float *)color4f;
8745         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8746         rsurface.modellightmapcolor4f_bufferoffset = 0;
8747         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8748         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8749         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8750         rsurface.modeltexcoordlightmap2f  = NULL;
8751         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8752         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8753         rsurface.modelskeletalindex4ub = NULL;
8754         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8755         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8756         rsurface.modelskeletalweight4ub = NULL;
8757         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8758         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8759         rsurface.modelelement3i = (int *)element3i;
8760         rsurface.modelelement3i_indexbuffer = NULL;
8761         rsurface.modelelement3i_bufferoffset = 0;
8762         rsurface.modelelement3s = (unsigned short *)element3s;
8763         rsurface.modelelement3s_indexbuffer = NULL;
8764         rsurface.modelelement3s_bufferoffset = 0;
8765         rsurface.modellightmapoffsets = NULL;
8766         rsurface.modelsurfaces = NULL;
8767         rsurface.batchgeneratedvertex = false;
8768         rsurface.batchfirstvertex = 0;
8769         rsurface.batchnumvertices = 0;
8770         rsurface.batchfirsttriangle = 0;
8771         rsurface.batchnumtriangles = 0;
8772         rsurface.batchvertex3f  = NULL;
8773         rsurface.batchvertex3f_vertexbuffer = NULL;
8774         rsurface.batchvertex3f_bufferoffset = 0;
8775         rsurface.batchsvector3f = NULL;
8776         rsurface.batchsvector3f_vertexbuffer = NULL;
8777         rsurface.batchsvector3f_bufferoffset = 0;
8778         rsurface.batchtvector3f = NULL;
8779         rsurface.batchtvector3f_vertexbuffer = NULL;
8780         rsurface.batchtvector3f_bufferoffset = 0;
8781         rsurface.batchnormal3f  = NULL;
8782         rsurface.batchnormal3f_vertexbuffer = NULL;
8783         rsurface.batchnormal3f_bufferoffset = 0;
8784         rsurface.batchlightmapcolor4f = NULL;
8785         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8786         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8787         rsurface.batchtexcoordtexture2f = NULL;
8788         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8789         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8790         rsurface.batchtexcoordlightmap2f = NULL;
8791         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8792         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8793         rsurface.batchskeletalindex4ub = NULL;
8794         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8795         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8796         rsurface.batchskeletalweight4ub = NULL;
8797         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8798         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8799         rsurface.batchvertexmesh = NULL;
8800         rsurface.batchvertexmesh_vertexbuffer = NULL;
8801         rsurface.batchvertexmesh_bufferoffset = 0;
8802         rsurface.batchelement3i = NULL;
8803         rsurface.batchelement3i_indexbuffer = NULL;
8804         rsurface.batchelement3i_bufferoffset = 0;
8805         rsurface.batchelement3s = NULL;
8806         rsurface.batchelement3s_indexbuffer = NULL;
8807         rsurface.batchelement3s_bufferoffset = 0;
8808         rsurface.passcolor4f = NULL;
8809         rsurface.passcolor4f_vertexbuffer = NULL;
8810         rsurface.passcolor4f_bufferoffset = 0;
8811         rsurface.forcecurrenttextureupdate = true;
8812
8813         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8814         {
8815                 if ((wantnormals || wanttangents) && !normal3f)
8816                 {
8817                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8818                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8819                 }
8820                 if (wanttangents && !svector3f)
8821                 {
8822                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8823                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8824                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8825                 }
8826         }
8827 }
8828
8829 float RSurf_FogPoint(const float *v)
8830 {
8831         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8832         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8833         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8834         float FogHeightFade = r_refdef.fogheightfade;
8835         float fogfrac;
8836         unsigned int fogmasktableindex;
8837         if (r_refdef.fogplaneviewabove)
8838                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8839         else
8840                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8841         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8842         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8843 }
8844
8845 float RSurf_FogVertex(const float *v)
8846 {
8847         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8848         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8849         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8850         float FogHeightFade = rsurface.fogheightfade;
8851         float fogfrac;
8852         unsigned int fogmasktableindex;
8853         if (r_refdef.fogplaneviewabove)
8854                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8855         else
8856                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8857         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8858         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8859 }
8860
8861 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8862 {
8863         int i;
8864         for (i = 0;i < numelements;i++)
8865                 outelement3i[i] = inelement3i[i] + adjust;
8866 }
8867
8868 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8869 extern cvar_t gl_vbo;
8870 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8871 {
8872         int deformindex;
8873         int firsttriangle;
8874         int numtriangles;
8875         int firstvertex;
8876         int endvertex;
8877         int numvertices;
8878         int surfacefirsttriangle;
8879         int surfacenumtriangles;
8880         int surfacefirstvertex;
8881         int surfaceendvertex;
8882         int surfacenumvertices;
8883         int batchnumsurfaces = texturenumsurfaces;
8884         int batchnumvertices;
8885         int batchnumtriangles;
8886         int needsupdate;
8887         int i, j;
8888         qboolean gaps;
8889         qboolean dynamicvertex;
8890         float amplitude;
8891         float animpos;
8892         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8893         float waveparms[4];
8894         unsigned char *ub;
8895         q3shaderinfo_deform_t *deform;
8896         const msurface_t *surface, *firstsurface;
8897         r_vertexmesh_t *vertexmesh;
8898         if (!texturenumsurfaces)
8899                 return;
8900         // find vertex range of this surface batch
8901         gaps = false;
8902         firstsurface = texturesurfacelist[0];
8903         firsttriangle = firstsurface->num_firsttriangle;
8904         batchnumvertices = 0;
8905         batchnumtriangles = 0;
8906         firstvertex = endvertex = firstsurface->num_firstvertex;
8907         for (i = 0;i < texturenumsurfaces;i++)
8908         {
8909                 surface = texturesurfacelist[i];
8910                 if (surface != firstsurface + i)
8911                         gaps = true;
8912                 surfacefirstvertex = surface->num_firstvertex;
8913                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8914                 surfacenumvertices = surface->num_vertices;
8915                 surfacenumtriangles = surface->num_triangles;
8916                 if (firstvertex > surfacefirstvertex)
8917                         firstvertex = surfacefirstvertex;
8918                 if (endvertex < surfaceendvertex)
8919                         endvertex = surfaceendvertex;
8920                 batchnumvertices += surfacenumvertices;
8921                 batchnumtriangles += surfacenumtriangles;
8922         }
8923
8924         r_refdef.stats[r_stat_batch_batches]++;
8925         if (gaps)
8926                 r_refdef.stats[r_stat_batch_withgaps]++;
8927         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8928         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8929         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8930
8931         // we now know the vertex range used, and if there are any gaps in it
8932         rsurface.batchfirstvertex = firstvertex;
8933         rsurface.batchnumvertices = endvertex - firstvertex;
8934         rsurface.batchfirsttriangle = firsttriangle;
8935         rsurface.batchnumtriangles = batchnumtriangles;
8936
8937         // this variable holds flags for which properties have been updated that
8938         // may require regenerating vertexmesh array...
8939         needsupdate = 0;
8940
8941         // check if any dynamic vertex processing must occur
8942         dynamicvertex = false;
8943
8944         // a cvar to force the dynamic vertex path to be taken, for debugging
8945         if (r_batch_debugdynamicvertexpath.integer)
8946         {
8947                 if (!dynamicvertex)
8948                 {
8949                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8950                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8951                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8952                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8953                 }
8954                 dynamicvertex = true;
8955         }
8956
8957         // if there is a chance of animated vertex colors, it's a dynamic batch
8958         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8959         {
8960                 if (!dynamicvertex)
8961                 {
8962                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8963                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8964                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8965                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8966                 }
8967                 dynamicvertex = true;
8968                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8969         }
8970
8971         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8972         {
8973                 switch (deform->deform)
8974                 {
8975                 default:
8976                 case Q3DEFORM_PROJECTIONSHADOW:
8977                 case Q3DEFORM_TEXT0:
8978                 case Q3DEFORM_TEXT1:
8979                 case Q3DEFORM_TEXT2:
8980                 case Q3DEFORM_TEXT3:
8981                 case Q3DEFORM_TEXT4:
8982                 case Q3DEFORM_TEXT5:
8983                 case Q3DEFORM_TEXT6:
8984                 case Q3DEFORM_TEXT7:
8985                 case Q3DEFORM_NONE:
8986                         break;
8987                 case Q3DEFORM_AUTOSPRITE:
8988                         if (!dynamicvertex)
8989                         {
8990                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8991                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8992                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8993                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8994                         }
8995                         dynamicvertex = true;
8996                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8997                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8998                         break;
8999                 case Q3DEFORM_AUTOSPRITE2:
9000                         if (!dynamicvertex)
9001                         {
9002                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9003                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9004                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9005                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9006                         }
9007                         dynamicvertex = true;
9008                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9009                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9010                         break;
9011                 case Q3DEFORM_NORMAL:
9012                         if (!dynamicvertex)
9013                         {
9014                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9015                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9016                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9017                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9018                         }
9019                         dynamicvertex = true;
9020                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9021                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9022                         break;
9023                 case Q3DEFORM_WAVE:
9024                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9025                                 break; // if wavefunc is a nop, ignore this transform
9026                         if (!dynamicvertex)
9027                         {
9028                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9029                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9030                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9031                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9032                         }
9033                         dynamicvertex = true;
9034                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9035                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9036                         break;
9037                 case Q3DEFORM_BULGE:
9038                         if (!dynamicvertex)
9039                         {
9040                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9041                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9042                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9043                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9044                         }
9045                         dynamicvertex = true;
9046                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9047                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9048                         break;
9049                 case Q3DEFORM_MOVE:
9050                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9051                                 break; // if wavefunc is a nop, ignore this transform
9052                         if (!dynamicvertex)
9053                         {
9054                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9055                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9056                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9057                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9058                         }
9059                         dynamicvertex = true;
9060                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9061                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9062                         break;
9063                 }
9064         }
9065         if (rsurface.texture->materialshaderpass)
9066         {
9067                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9068                 {
9069                 default:
9070                 case Q3TCGEN_TEXTURE:
9071                         break;
9072                 case Q3TCGEN_LIGHTMAP:
9073                         if (!dynamicvertex)
9074                         {
9075                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9076                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9077                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9078                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9079                         }
9080                         dynamicvertex = true;
9081                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9082                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9083                         break;
9084                 case Q3TCGEN_VECTOR:
9085                         if (!dynamicvertex)
9086                         {
9087                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9088                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9089                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9090                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9091                         }
9092                         dynamicvertex = true;
9093                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9094                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9095                         break;
9096                 case Q3TCGEN_ENVIRONMENT:
9097                         if (!dynamicvertex)
9098                         {
9099                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9100                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9101                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9102                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9103                         }
9104                         dynamicvertex = true;
9105                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9106                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9107                         break;
9108                 }
9109                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9110                 {
9111                         if (!dynamicvertex)
9112                         {
9113                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9114                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9115                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9116                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9117                         }
9118                         dynamicvertex = true;
9119                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9120                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9121                 }
9122         }
9123
9124         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9125         {
9126                 if (!dynamicvertex)
9127                 {
9128                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9129                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9130                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9131                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9132                 }
9133                 dynamicvertex = true;
9134                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9135         }
9136
9137         // when the model data has no vertex buffer (dynamic mesh), we need to
9138         // eliminate gaps
9139         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9140                 batchneed |= BATCHNEED_NOGAPS;
9141
9142         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9143         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9144         // we ensure this by treating the vertex batch as dynamic...
9145         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9146         {
9147                 if (!dynamicvertex)
9148                 {
9149                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9150                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9151                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9152                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9153                 }
9154                 dynamicvertex = true;
9155         }
9156
9157         if (dynamicvertex)
9158         {
9159                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9160                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9161                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9162                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9163                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9164                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9165                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9166                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9167         }
9168
9169         // if needsupdate, we have to do a dynamic vertex batch for sure
9170         if (needsupdate & batchneed)
9171         {
9172                 if (!dynamicvertex)
9173                 {
9174                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9175                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9176                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9177                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9178                 }
9179                 dynamicvertex = true;
9180         }
9181
9182         // see if we need to build vertexmesh from arrays
9183         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9184         {
9185                 if (!dynamicvertex)
9186                 {
9187                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9188                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9189                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9190                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9191                 }
9192                 dynamicvertex = true;
9193         }
9194
9195         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9196         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9197                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9198
9199         rsurface.batchvertex3f = rsurface.modelvertex3f;
9200         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9201         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9202         rsurface.batchsvector3f = rsurface.modelsvector3f;
9203         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9204         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9205         rsurface.batchtvector3f = rsurface.modeltvector3f;
9206         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9207         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9208         rsurface.batchnormal3f = rsurface.modelnormal3f;
9209         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9210         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9211         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9212         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9213         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9214         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9215         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9216         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9217         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9218         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9219         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9220         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9221         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9222         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9223         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9224         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9225         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9226         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9227         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9228         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9229         rsurface.batchelement3i = rsurface.modelelement3i;
9230         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9231         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9232         rsurface.batchelement3s = rsurface.modelelement3s;
9233         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9234         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9235         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9236         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9237         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9238         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9239         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9240
9241         // if any dynamic vertex processing has to occur in software, we copy the
9242         // entire surface list together before processing to rebase the vertices
9243         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9244         //
9245         // if any gaps exist and we do not have a static vertex buffer, we have to
9246         // copy the surface list together to avoid wasting upload bandwidth on the
9247         // vertices in the gaps.
9248         //
9249         // if gaps exist and we have a static vertex buffer, we can choose whether
9250         // to combine the index buffer ranges into one dynamic index buffer or
9251         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9252         //
9253         // in many cases the batch is reduced to one draw call.
9254
9255         rsurface.batchmultidraw = false;
9256         rsurface.batchmultidrawnumsurfaces = 0;
9257         rsurface.batchmultidrawsurfacelist = NULL;
9258
9259         if (!dynamicvertex)
9260         {
9261                 // static vertex data, just set pointers...
9262                 rsurface.batchgeneratedvertex = false;
9263                 // if there are gaps, we want to build a combined index buffer,
9264                 // otherwise use the original static buffer with an appropriate offset
9265                 if (gaps)
9266                 {
9267                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9268                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9269                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9270                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9271                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9272                         {
9273                                 rsurface.batchmultidraw = true;
9274                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9275                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9276                                 return;
9277                         }
9278                         // build a new triangle elements array for this batch
9279                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9280                         rsurface.batchfirsttriangle = 0;
9281                         numtriangles = 0;
9282                         for (i = 0;i < texturenumsurfaces;i++)
9283                         {
9284                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9285                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9286                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9287                                 numtriangles += surfacenumtriangles;
9288                         }
9289                         rsurface.batchelement3i_indexbuffer = NULL;
9290                         rsurface.batchelement3i_bufferoffset = 0;
9291                         rsurface.batchelement3s = NULL;
9292                         rsurface.batchelement3s_indexbuffer = NULL;
9293                         rsurface.batchelement3s_bufferoffset = 0;
9294                         if (endvertex <= 65536)
9295                         {
9296                                 // make a 16bit (unsigned short) index array if possible
9297                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9298                                 for (i = 0;i < numtriangles*3;i++)
9299                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9300                         }
9301                         // upload buffer data for the copytriangles batch
9302                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9303                         {
9304                                 if (rsurface.batchelement3s)
9305                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9306                                 else if (rsurface.batchelement3i)
9307                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9308                         }
9309                 }
9310                 else
9311                 {
9312                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9313                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9314                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9315                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9316                 }
9317                 return;
9318         }
9319
9320         // something needs software processing, do it for real...
9321         // we only directly handle separate array data in this case and then
9322         // generate interleaved data if needed...
9323         rsurface.batchgeneratedvertex = true;
9324         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9325         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9326         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9327         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9328
9329         // now copy the vertex data into a combined array and make an index array
9330         // (this is what Quake3 does all the time)
9331         // we also apply any skeletal animation here that would have been done in
9332         // the vertex shader, because most of the dynamic vertex animation cases
9333         // need actual vertex positions and normals
9334         //if (dynamicvertex)
9335         {
9336                 rsurface.batchvertexmesh = NULL;
9337                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9338                 rsurface.batchvertexmesh_bufferoffset = 0;
9339                 rsurface.batchvertex3f = NULL;
9340                 rsurface.batchvertex3f_vertexbuffer = NULL;
9341                 rsurface.batchvertex3f_bufferoffset = 0;
9342                 rsurface.batchsvector3f = NULL;
9343                 rsurface.batchsvector3f_vertexbuffer = NULL;
9344                 rsurface.batchsvector3f_bufferoffset = 0;
9345                 rsurface.batchtvector3f = NULL;
9346                 rsurface.batchtvector3f_vertexbuffer = NULL;
9347                 rsurface.batchtvector3f_bufferoffset = 0;
9348                 rsurface.batchnormal3f = NULL;
9349                 rsurface.batchnormal3f_vertexbuffer = NULL;
9350                 rsurface.batchnormal3f_bufferoffset = 0;
9351                 rsurface.batchlightmapcolor4f = NULL;
9352                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9353                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9354                 rsurface.batchtexcoordtexture2f = NULL;
9355                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9356                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9357                 rsurface.batchtexcoordlightmap2f = NULL;
9358                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9359                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9360                 rsurface.batchskeletalindex4ub = NULL;
9361                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9362                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9363                 rsurface.batchskeletalweight4ub = NULL;
9364                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9365                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9366                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9367                 rsurface.batchelement3i_indexbuffer = NULL;
9368                 rsurface.batchelement3i_bufferoffset = 0;
9369                 rsurface.batchelement3s = NULL;
9370                 rsurface.batchelement3s_indexbuffer = NULL;
9371                 rsurface.batchelement3s_bufferoffset = 0;
9372                 rsurface.batchskeletaltransform3x4buffer = NULL;
9373                 rsurface.batchskeletaltransform3x4offset = 0;
9374                 rsurface.batchskeletaltransform3x4size = 0;
9375                 // we'll only be setting up certain arrays as needed
9376                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9377                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9378                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9379                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9380                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9381                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9382                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9383                 {
9384                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9385                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9386                 }
9387                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9388                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9389                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9390                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9391                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9392                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9393                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9394                 {
9395                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9396                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9397                 }
9398                 numvertices = 0;
9399                 numtriangles = 0;
9400                 for (i = 0;i < texturenumsurfaces;i++)
9401                 {
9402                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9403                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9404                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9405                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9406                         // copy only the data requested
9407                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9408                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9409                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9410                         {
9411                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9412                                 {
9413                                         if (rsurface.batchvertex3f)
9414                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9415                                         else
9416                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9417                                 }
9418                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9419                                 {
9420                                         if (rsurface.modelnormal3f)
9421                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9422                                         else
9423                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9424                                 }
9425                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9426                                 {
9427                                         if (rsurface.modelsvector3f)
9428                                         {
9429                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9430                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9431                                         }
9432                                         else
9433                                         {
9434                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9435                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9436                                         }
9437                                 }
9438                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9439                                 {
9440                                         if (rsurface.modellightmapcolor4f)
9441                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9442                                         else
9443                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9444                                 }
9445                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9446                                 {
9447                                         if (rsurface.modeltexcoordtexture2f)
9448                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9449                                         else
9450                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9451                                 }
9452                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9453                                 {
9454                                         if (rsurface.modeltexcoordlightmap2f)
9455                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9456                                         else
9457                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9458                                 }
9459                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9460                                 {
9461                                         if (rsurface.modelskeletalindex4ub)
9462                                         {
9463                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9464                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9465                                         }
9466                                         else
9467                                         {
9468                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9469                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9470                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9471                                                 for (j = 0;j < surfacenumvertices;j++)
9472                                                         ub[j*4] = 255;
9473                                         }
9474                                 }
9475                         }
9476                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9477                         numvertices += surfacenumvertices;
9478                         numtriangles += surfacenumtriangles;
9479                 }
9480
9481                 // generate a 16bit index array as well if possible
9482                 // (in general, dynamic batches fit)
9483                 if (numvertices <= 65536)
9484                 {
9485                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9486                         for (i = 0;i < numtriangles*3;i++)
9487                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9488                 }
9489
9490                 // since we've copied everything, the batch now starts at 0
9491                 rsurface.batchfirstvertex = 0;
9492                 rsurface.batchnumvertices = batchnumvertices;
9493                 rsurface.batchfirsttriangle = 0;
9494                 rsurface.batchnumtriangles = batchnumtriangles;
9495         }
9496
9497         // apply skeletal animation that would have been done in the vertex shader
9498         if (rsurface.batchskeletaltransform3x4)
9499         {
9500                 const unsigned char *si;
9501                 const unsigned char *sw;
9502                 const float *t[4];
9503                 const float *b = rsurface.batchskeletaltransform3x4;
9504                 float *vp, *vs, *vt, *vn;
9505                 float w[4];
9506                 float m[3][4], n[3][4];
9507                 float tp[3], ts[3], tt[3], tn[3];
9508                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9509                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9510                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9511                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9512                 si = rsurface.batchskeletalindex4ub;
9513                 sw = rsurface.batchskeletalweight4ub;
9514                 vp = rsurface.batchvertex3f;
9515                 vs = rsurface.batchsvector3f;
9516                 vt = rsurface.batchtvector3f;
9517                 vn = rsurface.batchnormal3f;
9518                 memset(m[0], 0, sizeof(m));
9519                 memset(n[0], 0, sizeof(n));
9520                 for (i = 0;i < batchnumvertices;i++)
9521                 {
9522                         t[0] = b + si[0]*12;
9523                         if (sw[0] == 255)
9524                         {
9525                                 // common case - only one matrix
9526                                 m[0][0] = t[0][ 0];
9527                                 m[0][1] = t[0][ 1];
9528                                 m[0][2] = t[0][ 2];
9529                                 m[0][3] = t[0][ 3];
9530                                 m[1][0] = t[0][ 4];
9531                                 m[1][1] = t[0][ 5];
9532                                 m[1][2] = t[0][ 6];
9533                                 m[1][3] = t[0][ 7];
9534                                 m[2][0] = t[0][ 8];
9535                                 m[2][1] = t[0][ 9];
9536                                 m[2][2] = t[0][10];
9537                                 m[2][3] = t[0][11];
9538                         }
9539                         else if (sw[2] + sw[3])
9540                         {
9541                                 // blend 4 matrices
9542                                 t[1] = b + si[1]*12;
9543                                 t[2] = b + si[2]*12;
9544                                 t[3] = b + si[3]*12;
9545                                 w[0] = sw[0] * (1.0f / 255.0f);
9546                                 w[1] = sw[1] * (1.0f / 255.0f);
9547                                 w[2] = sw[2] * (1.0f / 255.0f);
9548                                 w[3] = sw[3] * (1.0f / 255.0f);
9549                                 // blend the matrices
9550                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9551                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9552                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9553                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9554                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9555                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9556                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9557                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9558                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9559                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9560                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9561                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9562                         }
9563                         else
9564                         {
9565                                 // blend 2 matrices
9566                                 t[1] = b + si[1]*12;
9567                                 w[0] = sw[0] * (1.0f / 255.0f);
9568                                 w[1] = sw[1] * (1.0f / 255.0f);
9569                                 // blend the matrices
9570                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9571                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9572                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9573                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9574                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9575                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9576                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9577                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9578                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9579                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9580                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9581                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9582                         }
9583                         si += 4;
9584                         sw += 4;
9585                         // modify the vertex
9586                         VectorCopy(vp, tp);
9587                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9588                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9589                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9590                         vp += 3;
9591                         if (vn)
9592                         {
9593                                 // the normal transformation matrix is a set of cross products...
9594                                 CrossProduct(m[1], m[2], n[0]);
9595                                 CrossProduct(m[2], m[0], n[1]);
9596                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9597                                 VectorCopy(vn, tn);
9598                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9599                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9600                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9601                                 VectorNormalize(vn);
9602                                 vn += 3;
9603                                 if (vs)
9604                                 {
9605                                         VectorCopy(vs, ts);
9606                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9607                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9608                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9609                                         VectorNormalize(vs);
9610                                         vs += 3;
9611                                         VectorCopy(vt, tt);
9612                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9613                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9614                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9615                                         VectorNormalize(vt);
9616                                         vt += 3;
9617                                 }
9618                         }
9619                 }
9620                 rsurface.batchskeletaltransform3x4 = NULL;
9621                 rsurface.batchskeletalnumtransforms = 0;
9622         }
9623
9624         // q1bsp surfaces rendered in vertex color mode have to have colors
9625         // calculated based on lightstyles
9626         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9627         {
9628                 // generate color arrays for the surfaces in this list
9629                 int c[4];
9630                 int scale;
9631                 int size3;
9632                 const int *offsets;
9633                 const unsigned char *lm;
9634                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9635                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9636                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9637                 numvertices = 0;
9638                 for (i = 0;i < texturenumsurfaces;i++)
9639                 {
9640                         surface = texturesurfacelist[i];
9641                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9642                         surfacenumvertices = surface->num_vertices;
9643                         if (surface->lightmapinfo->samples)
9644                         {
9645                                 for (j = 0;j < surfacenumvertices;j++)
9646                                 {
9647                                         lm = surface->lightmapinfo->samples + offsets[j];
9648                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9649                                         VectorScale(lm, scale, c);
9650                                         if (surface->lightmapinfo->styles[1] != 255)
9651                                         {
9652                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9653                                                 lm += size3;
9654                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9655                                                 VectorMA(c, scale, lm, c);
9656                                                 if (surface->lightmapinfo->styles[2] != 255)
9657                                                 {
9658                                                         lm += size3;
9659                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9660                                                         VectorMA(c, scale, lm, c);
9661                                                         if (surface->lightmapinfo->styles[3] != 255)
9662                                                         {
9663                                                                 lm += size3;
9664                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9665                                                                 VectorMA(c, scale, lm, c);
9666                                                         }
9667                                                 }
9668                                         }
9669                                         c[0] >>= 7;
9670                                         c[1] >>= 7;
9671                                         c[2] >>= 7;
9672                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
9673                                         numvertices++;
9674                                 }
9675                         }
9676                         else
9677                         {
9678                                 for (j = 0;j < surfacenumvertices;j++)
9679                                 {
9680                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9681                                         numvertices++;
9682                                 }
9683                         }
9684                 }
9685         }
9686
9687         // if vertices are deformed (sprite flares and things in maps, possibly
9688         // water waves, bulges and other deformations), modify the copied vertices
9689         // in place
9690         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9691         {
9692                 float scale;
9693                 switch (deform->deform)
9694                 {
9695                 default:
9696                 case Q3DEFORM_PROJECTIONSHADOW:
9697                 case Q3DEFORM_TEXT0:
9698                 case Q3DEFORM_TEXT1:
9699                 case Q3DEFORM_TEXT2:
9700                 case Q3DEFORM_TEXT3:
9701                 case Q3DEFORM_TEXT4:
9702                 case Q3DEFORM_TEXT5:
9703                 case Q3DEFORM_TEXT6:
9704                 case Q3DEFORM_TEXT7:
9705                 case Q3DEFORM_NONE:
9706                         break;
9707                 case Q3DEFORM_AUTOSPRITE:
9708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9709                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9710                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9711                         VectorNormalize(newforward);
9712                         VectorNormalize(newright);
9713                         VectorNormalize(newup);
9714 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9715 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9716 //                      rsurface.batchvertex3f_bufferoffset = 0;
9717 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9718 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9719 //                      rsurface.batchsvector3f_bufferoffset = 0;
9720 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9721 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9722 //                      rsurface.batchtvector3f_bufferoffset = 0;
9723 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9724 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9725 //                      rsurface.batchnormal3f_bufferoffset = 0;
9726                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9727                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9728                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9729                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9730                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9731                         // a single autosprite surface can contain multiple sprites...
9732                         for (j = 0;j < batchnumvertices - 3;j += 4)
9733                         {
9734                                 VectorClear(center);
9735                                 for (i = 0;i < 4;i++)
9736                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9737                                 VectorScale(center, 0.25f, center);
9738                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9739                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9740                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9741                                 for (i = 0;i < 4;i++)
9742                                 {
9743                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9744                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9745                                 }
9746                         }
9747                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9748                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9749                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9750                         break;
9751                 case Q3DEFORM_AUTOSPRITE2:
9752                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9753                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9754                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9755                         VectorNormalize(newforward);
9756                         VectorNormalize(newright);
9757                         VectorNormalize(newup);
9758 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9759 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9760 //                      rsurface.batchvertex3f_bufferoffset = 0;
9761                         {
9762                                 const float *v1, *v2;
9763                                 vec3_t start, end;
9764                                 float f, l;
9765                                 struct
9766                                 {
9767                                         float length2;
9768                                         const float *v1;
9769                                         const float *v2;
9770                                 }
9771                                 shortest[2];
9772                                 memset(shortest, 0, sizeof(shortest));
9773                                 // a single autosprite surface can contain multiple sprites...
9774                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9775                                 {
9776                                         VectorClear(center);
9777                                         for (i = 0;i < 4;i++)
9778                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9779                                         VectorScale(center, 0.25f, center);
9780                                         // find the two shortest edges, then use them to define the
9781                                         // axis vectors for rotating around the central axis
9782                                         for (i = 0;i < 6;i++)
9783                                         {
9784                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9785                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9786                                                 l = VectorDistance2(v1, v2);
9787                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9788                                                 if (v1[2] != v2[2])
9789                                                         l += (1.0f / 1024.0f);
9790                                                 if (shortest[0].length2 > l || i == 0)
9791                                                 {
9792                                                         shortest[1] = shortest[0];
9793                                                         shortest[0].length2 = l;
9794                                                         shortest[0].v1 = v1;
9795                                                         shortest[0].v2 = v2;
9796                                                 }
9797                                                 else if (shortest[1].length2 > l || i == 1)
9798                                                 {
9799                                                         shortest[1].length2 = l;
9800                                                         shortest[1].v1 = v1;
9801                                                         shortest[1].v2 = v2;
9802                                                 }
9803                                         }
9804                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9805                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9806                                         // this calculates the right vector from the shortest edge
9807                                         // and the up vector from the edge midpoints
9808                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9809                                         VectorNormalize(right);
9810                                         VectorSubtract(end, start, up);
9811                                         VectorNormalize(up);
9812                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9813                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9814                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9815                                         VectorNegate(forward, forward);
9816                                         VectorReflect(forward, 0, up, forward);
9817                                         VectorNormalize(forward);
9818                                         CrossProduct(up, forward, newright);
9819                                         VectorNormalize(newright);
9820                                         // rotate the quad around the up axis vector, this is made
9821                                         // especially easy by the fact we know the quad is flat,
9822                                         // so we only have to subtract the center position and
9823                                         // measure distance along the right vector, and then
9824                                         // multiply that by the newright vector and add back the
9825                                         // center position
9826                                         // we also need to subtract the old position to undo the
9827                                         // displacement from the center, which we do with a
9828                                         // DotProduct, the subtraction/addition of center is also
9829                                         // optimized into DotProducts here
9830                                         l = DotProduct(right, center);
9831                                         for (i = 0;i < 4;i++)
9832                                         {
9833                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9834                                                 f = DotProduct(right, v1) - l;
9835                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9836                                         }
9837                                 }
9838                         }
9839                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9840                         {
9841 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9842 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9843 //                              rsurface.batchnormal3f_bufferoffset = 0;
9844                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9845                         }
9846                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9847                         {
9848 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9849 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9850 //                              rsurface.batchsvector3f_bufferoffset = 0;
9851 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9852 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9853 //                              rsurface.batchtvector3f_bufferoffset = 0;
9854                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9855                         }
9856                         break;
9857                 case Q3DEFORM_NORMAL:
9858                         // deform the normals to make reflections wavey
9859                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9860                         rsurface.batchnormal3f_vertexbuffer = NULL;
9861                         rsurface.batchnormal3f_bufferoffset = 0;
9862                         for (j = 0;j < batchnumvertices;j++)
9863                         {
9864                                 float vertex[3];
9865                                 float *normal = rsurface.batchnormal3f + 3*j;
9866                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9867                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9868                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9869                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9870                                 VectorNormalize(normal);
9871                         }
9872                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9873                         {
9874 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9875 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9876 //                              rsurface.batchsvector3f_bufferoffset = 0;
9877 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9878 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9879 //                              rsurface.batchtvector3f_bufferoffset = 0;
9880                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9881                         }
9882                         break;
9883                 case Q3DEFORM_WAVE:
9884                         // deform vertex array to make wavey water and flags and such
9885                         waveparms[0] = deform->waveparms[0];
9886                         waveparms[1] = deform->waveparms[1];
9887                         waveparms[2] = deform->waveparms[2];
9888                         waveparms[3] = deform->waveparms[3];
9889                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9890                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9891                         // this is how a divisor of vertex influence on deformation
9892                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9893                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9894 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9895 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9896 //                      rsurface.batchvertex3f_bufferoffset = 0;
9897 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9898 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9899 //                      rsurface.batchnormal3f_bufferoffset = 0;
9900                         for (j = 0;j < batchnumvertices;j++)
9901                         {
9902                                 // if the wavefunc depends on time, evaluate it per-vertex
9903                                 if (waveparms[3])
9904                                 {
9905                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9906                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9907                                 }
9908                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9909                         }
9910                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9911                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9912                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9913                         {
9914 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9915 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9916 //                              rsurface.batchsvector3f_bufferoffset = 0;
9917 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9918 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9919 //                              rsurface.batchtvector3f_bufferoffset = 0;
9920                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9921                         }
9922                         break;
9923                 case Q3DEFORM_BULGE:
9924                         // deform vertex array to make the surface have moving bulges
9925 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9926 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9927 //                      rsurface.batchvertex3f_bufferoffset = 0;
9928 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9929 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9930 //                      rsurface.batchnormal3f_bufferoffset = 0;
9931                         for (j = 0;j < batchnumvertices;j++)
9932                         {
9933                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9934                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9935                         }
9936                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9937                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9938                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9939                         {
9940 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9941 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9942 //                              rsurface.batchsvector3f_bufferoffset = 0;
9943 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9944 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9945 //                              rsurface.batchtvector3f_bufferoffset = 0;
9946                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9947                         }
9948                         break;
9949                 case Q3DEFORM_MOVE:
9950                         // deform vertex array
9951                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9952                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9953                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9954                         VectorScale(deform->parms, scale, waveparms);
9955 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9956 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9957 //                      rsurface.batchvertex3f_bufferoffset = 0;
9958                         for (j = 0;j < batchnumvertices;j++)
9959                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9960                         break;
9961                 }
9962         }
9963
9964         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9965         {
9966         // generate texcoords based on the chosen texcoord source
9967                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9968                 {
9969                 default:
9970                 case Q3TCGEN_TEXTURE:
9971                         break;
9972                 case Q3TCGEN_LIGHTMAP:
9973         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9974         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9975         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9976                         if (rsurface.batchtexcoordlightmap2f)
9977                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9978                         break;
9979                 case Q3TCGEN_VECTOR:
9980         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9981         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9982         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9983                         for (j = 0;j < batchnumvertices;j++)
9984                         {
9985                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9986                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9987                         }
9988                         break;
9989                 case Q3TCGEN_ENVIRONMENT:
9990                         // make environment reflections using a spheremap
9991                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9992                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9993                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9994                         for (j = 0;j < batchnumvertices;j++)
9995                         {
9996                                 // identical to Q3A's method, but executed in worldspace so
9997                                 // carried models can be shiny too
9998
9999                                 float viewer[3], d, reflected[3], worldreflected[3];
10000
10001                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10002                                 // VectorNormalize(viewer);
10003
10004                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10005
10006                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10007                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10008                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10009                                 // note: this is proportinal to viewer, so we can normalize later
10010
10011                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10012                                 VectorNormalize(worldreflected);
10013
10014                                 // note: this sphere map only uses world x and z!
10015                                 // so positive and negative y will LOOK THE SAME.
10016                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10017                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10018                         }
10019                         break;
10020                 }
10021                 // the only tcmod that needs software vertex processing is turbulent, so
10022                 // check for it here and apply the changes if needed
10023                 // and we only support that as the first one
10024                 // (handling a mixture of turbulent and other tcmods would be problematic
10025                 //  without punting it entirely to a software path)
10026                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10027                 {
10028                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10029                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10030         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10031         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10032         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10033                         for (j = 0;j < batchnumvertices;j++)
10034                         {
10035                                 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10036                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10037                         }
10038                 }
10039         }
10040
10041         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10042         {
10043                 // convert the modified arrays to vertex structs
10044 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10045 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10046 //              rsurface.batchvertexmesh_bufferoffset = 0;
10047                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10048                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10049                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10050                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10051                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10052                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10053                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10054                 {
10055                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10056                         {
10057                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10058                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10059                         }
10060                 }
10061                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10062                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10063                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10064                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10065                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10066                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10067                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10068                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10069                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10070                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10071                 {
10072                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10073                         {
10074                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10075                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10076                         }
10077                 }
10078         }
10079
10080         // upload buffer data for the dynamic batch
10081         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10082         {
10083                 if (rsurface.batchvertexmesh)
10084                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10085                 else
10086                 {
10087                         if (rsurface.batchvertex3f)
10088                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10089                         if (rsurface.batchsvector3f)
10090                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10091                         if (rsurface.batchtvector3f)
10092                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10093                         if (rsurface.batchnormal3f)
10094                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10095                         if (rsurface.batchlightmapcolor4f)
10096                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10097                         if (rsurface.batchtexcoordtexture2f)
10098                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10099                         if (rsurface.batchtexcoordlightmap2f)
10100                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10101                         if (rsurface.batchskeletalindex4ub)
10102                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10103                         if (rsurface.batchskeletalweight4ub)
10104                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10105                 }
10106                 if (rsurface.batchelement3s)
10107                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10108                 else if (rsurface.batchelement3i)
10109                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10110         }
10111 }
10112
10113 void RSurf_DrawBatch(void)
10114 {
10115         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10116         // through the pipeline, killing it earlier in the pipeline would have
10117         // per-surface overhead rather than per-batch overhead, so it's best to
10118         // reject it here, before it hits glDraw.
10119         if (rsurface.batchnumtriangles == 0)
10120                 return;
10121 #if 0
10122         // batch debugging code
10123         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10124         {
10125                 int i;
10126                 int j;
10127                 int c;
10128                 const int *e;
10129                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10130                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10131                 {
10132                         c = e[i];
10133                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10134                         {
10135                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10136                                 {
10137                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10138                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
10139                                         break;
10140                                 }
10141                         }
10142                 }
10143         }
10144 #endif
10145         if (rsurface.batchmultidraw)
10146         {
10147                 // issue multiple draws rather than copying index data
10148                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10149                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10150                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10151                 for (i = 0;i < numsurfaces;)
10152                 {
10153                         // combine consecutive surfaces as one draw
10154                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10155                                 if (surfacelist[j] != surfacelist[k] + 1)
10156                                         break;
10157                         firstvertex = surfacelist[i]->num_firstvertex;
10158                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10159                         firsttriangle = surfacelist[i]->num_firsttriangle;
10160                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10161                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10162                         i = j;
10163                 }
10164         }
10165         else
10166         {
10167                 // there is only one consecutive run of index data (may have been combined)
10168                 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10169         }
10170 }
10171
10172 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10173 {
10174         // pick the closest matching water plane
10175         int planeindex, vertexindex, bestplaneindex = -1;
10176         float d, bestd;
10177         vec3_t vert;
10178         const float *v;
10179         r_waterstate_waterplane_t *p;
10180         qboolean prepared = false;
10181         bestd = 0;
10182         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10183         {
10184                 if(p->camera_entity != rsurface.texture->camera_entity)
10185                         continue;
10186                 d = 0;
10187                 if(!prepared)
10188                 {
10189                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10190                         prepared = true;
10191                         if(rsurface.batchnumvertices == 0)
10192                                 break;
10193                 }
10194                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10195                 {
10196                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10197                         d += fabs(PlaneDiff(vert, &p->plane));
10198                 }
10199                 if (bestd > d || bestplaneindex < 0)
10200                 {
10201                         bestd = d;
10202                         bestplaneindex = planeindex;
10203                 }
10204         }
10205         return bestplaneindex;
10206         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10207         // this situation though, as it might be better to render single larger
10208         // batches with useless stuff (backface culled for example) than to
10209         // render multiple smaller batches
10210 }
10211
10212 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10213 {
10214         int i;
10215         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10216         rsurface.passcolor4f_vertexbuffer = 0;
10217         rsurface.passcolor4f_bufferoffset = 0;
10218         for (i = 0;i < rsurface.batchnumvertices;i++)
10219                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10220 }
10221
10222 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10223 {
10224         int i;
10225         float f;
10226         const float *v;
10227         const float *c;
10228         float *c2;
10229         if (rsurface.passcolor4f)
10230         {
10231                 // generate color arrays
10232                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10233                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10234                 rsurface.passcolor4f_vertexbuffer = 0;
10235                 rsurface.passcolor4f_bufferoffset = 0;
10236                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10237                 {
10238                         f = RSurf_FogVertex(v);
10239                         c2[0] = c[0] * f;
10240                         c2[1] = c[1] * f;
10241                         c2[2] = c[2] * f;
10242                         c2[3] = c[3];
10243                 }
10244         }
10245         else
10246         {
10247                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10248                 rsurface.passcolor4f_vertexbuffer = 0;
10249                 rsurface.passcolor4f_bufferoffset = 0;
10250                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10251                 {
10252                         f = RSurf_FogVertex(v);
10253                         c2[0] = f;
10254                         c2[1] = f;
10255                         c2[2] = f;
10256                         c2[3] = 1;
10257                 }
10258         }
10259 }
10260
10261 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10262 {
10263         int i;
10264         float f;
10265         const float *v;
10266         const float *c;
10267         float *c2;
10268         if (!rsurface.passcolor4f)
10269                 return;
10270         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10271         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10272         rsurface.passcolor4f_vertexbuffer = 0;
10273         rsurface.passcolor4f_bufferoffset = 0;
10274         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10275         {
10276                 f = RSurf_FogVertex(v);
10277                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10278                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10279                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10280                 c2[3] = c[3];
10281         }
10282 }
10283
10284 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10285 {
10286         int i;
10287         const float *c;
10288         float *c2;
10289         if (!rsurface.passcolor4f)
10290                 return;
10291         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10292         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10293         rsurface.passcolor4f_vertexbuffer = 0;
10294         rsurface.passcolor4f_bufferoffset = 0;
10295         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10296         {
10297                 c2[0] = c[0] * r;
10298                 c2[1] = c[1] * g;
10299                 c2[2] = c[2] * b;
10300                 c2[3] = c[3] * a;
10301         }
10302 }
10303
10304 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10305 {
10306         int i;
10307         const float *c;
10308         float *c2;
10309         if (!rsurface.passcolor4f)
10310                 return;
10311         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10312         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10313         rsurface.passcolor4f_vertexbuffer = 0;
10314         rsurface.passcolor4f_bufferoffset = 0;
10315         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10316         {
10317                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10318                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10319                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10320                 c2[3] = c[3];
10321         }
10322 }
10323
10324 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10325 {
10326         // TODO: optimize
10327         rsurface.passcolor4f = NULL;
10328         rsurface.passcolor4f_vertexbuffer = 0;
10329         rsurface.passcolor4f_bufferoffset = 0;
10330         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10331         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10332         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10333         GL_Color(r, g, b, a);
10334         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10335         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10336         R_Mesh_TexMatrix(0, NULL);
10337         RSurf_DrawBatch();
10338 }
10339
10340 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10341 {
10342         // TODO: optimize applyfog && applycolor case
10343         // just apply fog if necessary, and tint the fog color array if necessary
10344         rsurface.passcolor4f = NULL;
10345         rsurface.passcolor4f_vertexbuffer = 0;
10346         rsurface.passcolor4f_bufferoffset = 0;
10347         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10348         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10349         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10350         GL_Color(r, g, b, a);
10351         RSurf_DrawBatch();
10352 }
10353
10354 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10355 {
10356         // TODO: optimize
10357         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10358         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10359         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10360         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10361         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10362         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10363         GL_Color(r, g, b, a);
10364         RSurf_DrawBatch();
10365 }
10366
10367 static void RSurf_DrawBatch_GL11_ClampColor(void)
10368 {
10369         int i;
10370         const float *c1;
10371         float *c2;
10372         if (!rsurface.passcolor4f)
10373                 return;
10374         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10375         {
10376                 c2[0] = bound(0.0f, c1[0], 1.0f);
10377                 c2[1] = bound(0.0f, c1[1], 1.0f);
10378                 c2[2] = bound(0.0f, c1[2], 1.0f);
10379                 c2[3] = bound(0.0f, c1[3], 1.0f);
10380         }
10381 }
10382
10383 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10384 {
10385         int i;
10386         float f;
10387         const float *v;
10388         const float *n;
10389         float *c;
10390         //vec3_t eyedir;
10391
10392         // fake shading
10393         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394         rsurface.passcolor4f_vertexbuffer = 0;
10395         rsurface.passcolor4f_bufferoffset = 0;
10396         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10397         {
10398                 f = -DotProduct(r_refdef.view.forward, n);
10399                 f = max(0, f);
10400                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10401                 f *= fakelightintensity;
10402                 Vector4Set(c, f, f, f, 1);
10403         }
10404 }
10405
10406 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10407 {
10408         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10409         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10410         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10411         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10412         GL_Color(r, g, b, a);
10413         RSurf_DrawBatch();
10414 }
10415
10416 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10417 {
10418         int i;
10419         float f;
10420         float alpha;
10421         const float *v;
10422         const float *n;
10423         float *c;
10424         vec3_t ambientcolor;
10425         vec3_t diffusecolor;
10426         vec3_t lightdir;
10427         // TODO: optimize
10428         // model lighting
10429         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10430         f = 0.5f * lightmapintensity;
10431         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10432         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10433         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10434         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10435         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10436         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10437         alpha = *a;
10438         if (VectorLength2(diffusecolor) > 0)
10439         {
10440                 // q3-style directional shading
10441                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10442                 rsurface.passcolor4f_vertexbuffer = 0;
10443                 rsurface.passcolor4f_bufferoffset = 0;
10444                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10445                 {
10446                         if ((f = DotProduct(n, lightdir)) > 0)
10447                                 VectorMA(ambientcolor, f, diffusecolor, c);
10448                         else
10449                                 VectorCopy(ambientcolor, c);
10450                         c[3] = alpha;
10451                 }
10452                 *r = 1;
10453                 *g = 1;
10454                 *b = 1;
10455                 *a = 1;
10456                 *applycolor = false;
10457         }
10458         else
10459         {
10460                 *r = ambientcolor[0];
10461                 *g = ambientcolor[1];
10462                 *b = ambientcolor[2];
10463                 rsurface.passcolor4f = NULL;
10464                 rsurface.passcolor4f_vertexbuffer = 0;
10465                 rsurface.passcolor4f_bufferoffset = 0;
10466         }
10467 }
10468
10469 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10470 {
10471         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10472         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10473         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10474         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10475         GL_Color(r, g, b, a);
10476         RSurf_DrawBatch();
10477 }
10478
10479 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10480 {
10481         int i;
10482         float f;
10483         const float *v;
10484         float *c;
10485
10486         // fake shading
10487         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10488         rsurface.passcolor4f_vertexbuffer = 0;
10489         rsurface.passcolor4f_bufferoffset = 0;
10490
10491         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10492         {
10493                 f = 1 - RSurf_FogVertex(v);
10494                 c[0] = r;
10495                 c[1] = g;
10496                 c[2] = b;
10497                 c[3] = f * a;
10498         }
10499 }
10500
10501 void RSurf_SetupDepthAndCulling(void)
10502 {
10503         // submodels are biased to avoid z-fighting with world surfaces that they
10504         // may be exactly overlapping (avoids z-fighting artifacts on certain
10505         // doors and things in Quake maps)
10506         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10507         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10508         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10509         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10510 }
10511
10512 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10513 {
10514         // transparent sky would be ridiculous
10515         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10516                 return;
10517         R_SetupShader_Generic_NoTexture(false, false);
10518         skyrenderlater = true;
10519         RSurf_SetupDepthAndCulling();
10520         GL_DepthMask(true);
10521         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10522         // skymasking on them, and Quake3 never did sky masking (unlike
10523         // software Quake and software Quake2), so disable the sky masking
10524         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10525         // and skymasking also looks very bad when noclipping outside the
10526         // level, so don't use it then either.
10527         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10528         {
10529                 R_Mesh_ResetTextureState();
10530                 if (skyrendermasked)
10531                 {
10532                         R_SetupShader_DepthOrShadow(false, false, false);
10533                         // depth-only (masking)
10534                         GL_ColorMask(0,0,0,0);
10535                         // just to make sure that braindead drivers don't draw
10536                         // anything despite that colormask...
10537                         GL_BlendFunc(GL_ZERO, GL_ONE);
10538                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10539                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10540                 }
10541                 else
10542                 {
10543                         R_SetupShader_Generic_NoTexture(false, false);
10544                         // fog sky
10545                         GL_BlendFunc(GL_ONE, GL_ZERO);
10546                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10547                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10548                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10549                 }
10550                 RSurf_DrawBatch();
10551                 if (skyrendermasked)
10552                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10553         }
10554         R_Mesh_ResetTextureState();
10555         GL_Color(1, 1, 1, 1);
10556 }
10557
10558 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10559 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10560 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10561 {
10562         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10563                 return;
10564         if (prepass)
10565         {
10566                 // render screenspace normalmap to texture
10567                 GL_DepthMask(true);
10568                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10569                 RSurf_DrawBatch();
10570                 return;
10571         }
10572
10573         // bind lightmap texture
10574
10575         // water/refraction/reflection/camera surfaces have to be handled specially
10576         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10577         {
10578                 int start, end, startplaneindex;
10579                 for (start = 0;start < texturenumsurfaces;start = end)
10580                 {
10581                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10582                         if(startplaneindex < 0)
10583                         {
10584                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10585                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10586                                 end = start + 1;
10587                                 continue;
10588                         }
10589                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10590                                 ;
10591                         // now that we have a batch using the same planeindex, render it
10592                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10593                         {
10594                                 // render water or distortion background
10595                                 GL_DepthMask(true);
10596                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10597                                 RSurf_DrawBatch();
10598                                 // blend surface on top
10599                                 GL_DepthMask(false);
10600                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10601                                 RSurf_DrawBatch();
10602                         }
10603                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10604                         {
10605                                 // render surface with reflection texture as input
10606                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10607                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10608                                 RSurf_DrawBatch();
10609                         }
10610                 }
10611                 return;
10612         }
10613
10614         // render surface batch normally
10615         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10616         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10617         RSurf_DrawBatch();
10618 }
10619
10620 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10621 {
10622         // OpenGL 1.3 path - anything not completely ancient
10623         qboolean applycolor;
10624         qboolean applyfog;
10625         int layerindex;
10626         const texturelayer_t *layer;
10627         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);
10628         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10629
10630         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10631         {
10632                 vec4_t layercolor;
10633                 int layertexrgbscale;
10634                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10635                 {
10636                         if (layerindex == 0)
10637                                 GL_AlphaTest(true);
10638                         else
10639                         {
10640                                 GL_AlphaTest(false);
10641                                 GL_DepthFunc(GL_EQUAL);
10642                         }
10643                 }
10644                 GL_DepthMask(layer->depthmask && writedepth);
10645                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10646                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10647                 {
10648                         layertexrgbscale = 4;
10649                         VectorScale(layer->color, 0.25f, layercolor);
10650                 }
10651                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10652                 {
10653                         layertexrgbscale = 2;
10654                         VectorScale(layer->color, 0.5f, layercolor);
10655                 }
10656                 else
10657                 {
10658                         layertexrgbscale = 1;
10659                         VectorScale(layer->color, 1.0f, layercolor);
10660                 }
10661                 layercolor[3] = layer->color[3];
10662                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10663                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10664                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10665                 switch (layer->type)
10666                 {
10667                 case TEXTURELAYERTYPE_LITTEXTURE:
10668                         // single-pass lightmapped texture with 2x rgbscale
10669                         R_Mesh_TexBind(0, r_texture_white);
10670                         R_Mesh_TexMatrix(0, NULL);
10671                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10672                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10673                         R_Mesh_TexBind(1, layer->texture);
10674                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10675                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10676                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10677                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10678                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10679                         else if (FAKELIGHT_ENABLED)
10680                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10681                         else if (rsurface.uselightmaptexture)
10682                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10683                         else
10684                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10685                         break;
10686                 case TEXTURELAYERTYPE_TEXTURE:
10687                         // singletexture unlit texture with transparency support
10688                         R_Mesh_TexBind(0, layer->texture);
10689                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10690                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10691                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10692                         R_Mesh_TexBind(1, 0);
10693                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10694                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10695                         break;
10696                 case TEXTURELAYERTYPE_FOG:
10697                         // singletexture fogging
10698                         if (layer->texture)
10699                         {
10700                                 R_Mesh_TexBind(0, layer->texture);
10701                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10702                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10703                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10704                         }
10705                         else
10706                         {
10707                                 R_Mesh_TexBind(0, 0);
10708                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10709                         }
10710                         R_Mesh_TexBind(1, 0);
10711                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10712                         // generate a color array for the fog pass
10713                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10714                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10715                         RSurf_DrawBatch();
10716                         break;
10717                 default:
10718                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10719                 }
10720         }
10721         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10722         {
10723                 GL_DepthFunc(GL_LEQUAL);
10724                 GL_AlphaTest(false);
10725         }
10726 }
10727
10728 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10729 {
10730         // OpenGL 1.1 - crusty old voodoo path
10731         qboolean applyfog;
10732         int layerindex;
10733         const texturelayer_t *layer;
10734         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);
10735         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10736
10737         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10738         {
10739                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10740                 {
10741                         if (layerindex == 0)
10742                                 GL_AlphaTest(true);
10743                         else
10744                         {
10745                                 GL_AlphaTest(false);
10746                                 GL_DepthFunc(GL_EQUAL);
10747                         }
10748                 }
10749                 GL_DepthMask(layer->depthmask && writedepth);
10750                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10751                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10752                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10753                 switch (layer->type)
10754                 {
10755                 case TEXTURELAYERTYPE_LITTEXTURE:
10756                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10757                         {
10758                                 // two-pass lit texture with 2x rgbscale
10759                                 // first the lightmap pass
10760                                 R_Mesh_TexBind(0, r_texture_white);
10761                                 R_Mesh_TexMatrix(0, NULL);
10762                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10763                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10764                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10765                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10766                                 else if (FAKELIGHT_ENABLED)
10767                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10768                                 else if (rsurface.uselightmaptexture)
10769                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10770                                 else
10771                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10772                                 // then apply the texture to it
10773                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10774                                 R_Mesh_TexBind(0, layer->texture);
10775                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10776                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10777                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10778                                 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);
10779                         }
10780                         else
10781                         {
10782                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10783                                 R_Mesh_TexBind(0, layer->texture);
10784                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10785                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10786                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10787                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10788                                         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);
10789                                 else if (FAKELIGHT_ENABLED)
10790                                         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);
10791                                 else
10792                                         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);
10793                         }
10794                         break;
10795                 case TEXTURELAYERTYPE_TEXTURE:
10796                         // singletexture unlit texture with transparency support
10797                         R_Mesh_TexBind(0, layer->texture);
10798                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10799                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10800                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10801                         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);
10802                         break;
10803                 case TEXTURELAYERTYPE_FOG:
10804                         // singletexture fogging
10805                         if (layer->texture)
10806                         {
10807                                 R_Mesh_TexBind(0, layer->texture);
10808                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10809                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10810                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10811                         }
10812                         else
10813                         {
10814                                 R_Mesh_TexBind(0, 0);
10815                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10816                         }
10817                         // generate a color array for the fog pass
10818                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10819                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10820                         RSurf_DrawBatch();
10821                         break;
10822                 default:
10823                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10824                 }
10825         }
10826         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10827         {
10828                 GL_DepthFunc(GL_LEQUAL);
10829                 GL_AlphaTest(false);
10830         }
10831 }
10832
10833 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10834 {
10835         int vi;
10836         int j;
10837         r_vertexgeneric_t *batchvertex;
10838         float c[4];
10839         texture_t *t = rsurface.texture;
10840
10841 //      R_Mesh_ResetTextureState();
10842         R_SetupShader_Generic_NoTexture(false, false);
10843
10844         if(t && t->currentskinframe)
10845         {
10846                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10847                 c[3] *= t->currentalpha;
10848         }
10849         else
10850         {
10851                 c[0] = 1;
10852                 c[1] = 0;
10853                 c[2] = 1;
10854                 c[3] = 1;
10855         }
10856
10857         if (t->pantstexture || t->shirttexture)
10858         {
10859                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10860                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10861                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10862         }
10863
10864         // brighten it up (as texture value 127 means "unlit")
10865         c[0] *= 2 * r_refdef.view.colorscale;
10866         c[1] *= 2 * r_refdef.view.colorscale;
10867         c[2] *= 2 * r_refdef.view.colorscale;
10868
10869         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10870                 c[3] *= r_wateralpha.value;
10871
10872         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10873         {
10874                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10875                 GL_DepthMask(false);
10876         }
10877         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10878         {
10879                 GL_BlendFunc(GL_ONE, GL_ONE);
10880                 GL_DepthMask(false);
10881         }
10882         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10883         {
10884                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10885                 GL_DepthMask(false);
10886         }
10887         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10888         {
10889                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10890                 GL_DepthMask(false);
10891         }
10892         else
10893         {
10894                 GL_BlendFunc(GL_ONE, GL_ZERO);
10895                 GL_DepthMask(writedepth);
10896         }
10897
10898         if (r_showsurfaces.integer == 3)
10899         {
10900                 rsurface.passcolor4f = NULL;
10901
10902                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10903                 {
10904                         qboolean applycolor = true;
10905                         float one = 1.0;
10906
10907                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10908
10909                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10910                 }
10911                 else if (FAKELIGHT_ENABLED)
10912                 {
10913                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10914
10915                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10916                 }
10917                 else
10918                 {
10919                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10920
10921                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10922                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10923                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10924                         RSurf_DrawBatch_GL11_ApplyAmbient();
10925                 }
10926
10927                 if(!rsurface.passcolor4f)
10928                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10929
10930                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10931                 if(r_refdef.fogenabled)
10932                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10933                 RSurf_DrawBatch_GL11_ClampColor();
10934
10935                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10936                 R_SetupShader_Generic_NoTexture(false, false);
10937                 RSurf_DrawBatch();
10938         }
10939         else if (!r_refdef.view.showdebug)
10940         {
10941                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10942                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10943                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10944                 {
10945                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10946                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10947                 }
10948                 R_Mesh_PrepareVertices_Generic_Unlock();
10949                 RSurf_DrawBatch();
10950         }
10951         else if (r_showsurfaces.integer == 4)
10952         {
10953                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10954                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10955                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10956                 {
10957                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
10958                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10959                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10960                 }
10961                 R_Mesh_PrepareVertices_Generic_Unlock();
10962                 RSurf_DrawBatch();
10963         }
10964         else if (r_showsurfaces.integer == 2)
10965         {
10966                 const int *e;
10967                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10968                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10969                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10970                 {
10971                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10972                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10973                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10974                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10975                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10976                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10977                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10978                 }
10979                 R_Mesh_PrepareVertices_Generic_Unlock();
10980                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10981         }
10982         else
10983         {
10984                 int texturesurfaceindex;
10985                 int k;
10986                 const msurface_t *surface;
10987                 float surfacecolor4f[4];
10988                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10989                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10990                 vi = 0;
10991                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10992                 {
10993                         surface = texturesurfacelist[texturesurfaceindex];
10994                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10995                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10996                         for (j = 0;j < surface->num_vertices;j++)
10997                         {
10998                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10999                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11000                                 vi++;
11001                         }
11002                 }
11003                 R_Mesh_PrepareVertices_Generic_Unlock();
11004                 RSurf_DrawBatch();
11005         }
11006 }
11007
11008 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11009 {
11010         CHECKGLERROR
11011         RSurf_SetupDepthAndCulling();
11012         if (r_showsurfaces.integer)
11013         {
11014                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11015                 return;
11016         }
11017         switch (vid.renderpath)
11018         {
11019         case RENDERPATH_GL20:
11020         case RENDERPATH_D3D9:
11021         case RENDERPATH_D3D10:
11022         case RENDERPATH_D3D11:
11023         case RENDERPATH_SOFT:
11024         case RENDERPATH_GLES2:
11025                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11026                 break;
11027         case RENDERPATH_GL13:
11028         case RENDERPATH_GLES1:
11029                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11030                 break;
11031         case RENDERPATH_GL11:
11032                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11033                 break;
11034         }
11035         CHECKGLERROR
11036 }
11037
11038 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11039 {
11040         int i, j;
11041         int texturenumsurfaces, endsurface;
11042         texture_t *texture;
11043         const msurface_t *surface;
11044         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11045
11046         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11047                 RSurf_ActiveModelEntity(ent, false, false, false);
11048         else
11049         {
11050                 switch (vid.renderpath)
11051                 {
11052                 case RENDERPATH_GL20:
11053                 case RENDERPATH_D3D9:
11054                 case RENDERPATH_D3D10:
11055                 case RENDERPATH_D3D11:
11056                 case RENDERPATH_SOFT:
11057                 case RENDERPATH_GLES2:
11058                         RSurf_ActiveModelEntity(ent, true, true, false);
11059                         break;
11060                 case RENDERPATH_GL11:
11061                 case RENDERPATH_GL13:
11062                 case RENDERPATH_GLES1:
11063                         RSurf_ActiveModelEntity(ent, true, false, false);
11064                         break;
11065                 }
11066         }
11067
11068         if (r_transparentdepthmasking.integer)
11069         {
11070                 qboolean setup = false;
11071                 for (i = 0;i < numsurfaces;i = j)
11072                 {
11073                         j = i + 1;
11074                         surface = rsurface.modelsurfaces + surfacelist[i];
11075                         texture = surface->texture;
11076                         rsurface.texture = R_GetCurrentTexture(texture);
11077                         rsurface.lightmaptexture = NULL;
11078                         rsurface.deluxemaptexture = NULL;
11079                         rsurface.uselightmaptexture = false;
11080                         // scan ahead until we find a different texture
11081                         endsurface = min(i + 1024, numsurfaces);
11082                         texturenumsurfaces = 0;
11083                         texturesurfacelist[texturenumsurfaces++] = surface;
11084                         for (;j < endsurface;j++)
11085                         {
11086                                 surface = rsurface.modelsurfaces + surfacelist[j];
11087                                 if (texture != surface->texture)
11088                                         break;
11089                                 texturesurfacelist[texturenumsurfaces++] = surface;
11090                         }
11091                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11092                                 continue;
11093                         // render the range of surfaces as depth
11094                         if (!setup)
11095                         {
11096                                 setup = true;
11097                                 GL_ColorMask(0,0,0,0);
11098                                 GL_Color(1,1,1,1);
11099                                 GL_DepthTest(true);
11100                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11101                                 GL_DepthMask(true);
11102 //                              R_Mesh_ResetTextureState();
11103                         }
11104                         RSurf_SetupDepthAndCulling();
11105                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11106                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11107                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11108                         RSurf_DrawBatch();
11109                 }
11110                 if (setup)
11111                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11112         }
11113
11114         for (i = 0;i < numsurfaces;i = j)
11115         {
11116                 j = i + 1;
11117                 surface = rsurface.modelsurfaces + surfacelist[i];
11118                 texture = surface->texture;
11119                 rsurface.texture = R_GetCurrentTexture(texture);
11120                 // scan ahead until we find a different texture
11121                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11122                 texturenumsurfaces = 0;
11123                 texturesurfacelist[texturenumsurfaces++] = surface;
11124                 if(FAKELIGHT_ENABLED)
11125                 {
11126                         rsurface.lightmaptexture = NULL;
11127                         rsurface.deluxemaptexture = NULL;
11128                         rsurface.uselightmaptexture = false;
11129                         for (;j < endsurface;j++)
11130                         {
11131                                 surface = rsurface.modelsurfaces + surfacelist[j];
11132                                 if (texture != surface->texture)
11133                                         break;
11134                                 texturesurfacelist[texturenumsurfaces++] = surface;
11135                         }
11136                 }
11137                 else
11138                 {
11139                         rsurface.lightmaptexture = surface->lightmaptexture;
11140                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11141                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11142                         for (;j < endsurface;j++)
11143                         {
11144                                 surface = rsurface.modelsurfaces + surfacelist[j];
11145                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11146                                         break;
11147                                 texturesurfacelist[texturenumsurfaces++] = surface;
11148                         }
11149                 }
11150                 // render the range of surfaces
11151                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11152         }
11153         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11154 }
11155
11156 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11157 {
11158         // transparent surfaces get pushed off into the transparent queue
11159         int surfacelistindex;
11160         const msurface_t *surface;
11161         vec3_t tempcenter, center;
11162         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11163         {
11164                 surface = texturesurfacelist[surfacelistindex];
11165                 if (r_transparent_sortsurfacesbynearest.integer)
11166                 {
11167                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11168                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11169                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11170                 }
11171                 else
11172                 {
11173                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11174                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11175                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11176                 }
11177                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11178                 if (rsurface.entity->transparent_offset) // transparent offset
11179                 {
11180                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11181                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11182                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11183                 }
11184                 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);
11185         }
11186 }
11187
11188 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11189 {
11190         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11191                 return;
11192         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11193                 return;
11194         RSurf_SetupDepthAndCulling();
11195         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11196         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11197         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11198         RSurf_DrawBatch();
11199 }
11200
11201 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11202 {
11203         CHECKGLERROR
11204         if (depthonly)
11205                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11206         else if (prepass)
11207         {
11208                 if (!rsurface.texture->currentnumlayers)
11209                         return;
11210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11211                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11212                 else
11213                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11214         }
11215         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11216                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11217         else if (!rsurface.texture->currentnumlayers)
11218                 return;
11219         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11220         {
11221                 // in the deferred case, transparent surfaces were queued during prepass
11222                 if (!r_shadow_usingdeferredprepass)
11223                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11224         }
11225         else
11226         {
11227                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11228                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11229         }
11230         CHECKGLERROR
11231 }
11232
11233 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11234 {
11235         int i, j;
11236         texture_t *texture;
11237         R_FrameData_SetMark();
11238         // break the surface list down into batches by texture and use of lightmapping
11239         for (i = 0;i < numsurfaces;i = j)
11240         {
11241                 j = i + 1;
11242                 // texture is the base texture pointer, rsurface.texture is the
11243                 // current frame/skin the texture is directing us to use (for example
11244                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11245                 // use skin 1 instead)
11246                 texture = surfacelist[i]->texture;
11247                 rsurface.texture = R_GetCurrentTexture(texture);
11248                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11249                 {
11250                         // if this texture is not the kind we want, skip ahead to the next one
11251                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11252                                 ;
11253                         continue;
11254                 }
11255                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11256                 {
11257                         rsurface.lightmaptexture = NULL;
11258                         rsurface.deluxemaptexture = NULL;
11259                         rsurface.uselightmaptexture = false;
11260                         // simply scan ahead until we find a different texture or lightmap state
11261                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11262                                 ;
11263                 }
11264                 else
11265                 {
11266                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11267                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11268                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11269                         // simply scan ahead until we find a different texture or lightmap state
11270                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11271                                 ;
11272                 }
11273                 // render the range of surfaces
11274                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11275         }
11276         R_FrameData_ReturnToMark();
11277 }
11278
11279 float locboxvertex3f[6*4*3] =
11280 {
11281         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11282         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11283         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11284         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11285         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11286         1,0,0, 0,0,0, 0,1,0, 1,1,0
11287 };
11288
11289 unsigned short locboxelements[6*2*3] =
11290 {
11291          0, 1, 2, 0, 2, 3,
11292          4, 5, 6, 4, 6, 7,
11293          8, 9,10, 8,10,11,
11294         12,13,14, 12,14,15,
11295         16,17,18, 16,18,19,
11296         20,21,22, 20,22,23
11297 };
11298
11299 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11300 {
11301         int i, j;
11302         cl_locnode_t *loc = (cl_locnode_t *)ent;
11303         vec3_t mins, size;
11304         float vertex3f[6*4*3];
11305         CHECKGLERROR
11306         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11307         GL_DepthMask(false);
11308         GL_DepthRange(0, 1);
11309         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11310         GL_DepthTest(true);
11311         GL_CullFace(GL_NONE);
11312         R_EntityMatrix(&identitymatrix);
11313
11314 //      R_Mesh_ResetTextureState();
11315
11316         i = surfacelist[0];
11317         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11318                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11319                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11320                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11321
11322         if (VectorCompare(loc->mins, loc->maxs))
11323         {
11324                 VectorSet(size, 2, 2, 2);
11325                 VectorMA(loc->mins, -0.5f, size, mins);
11326         }
11327         else
11328         {
11329                 VectorCopy(loc->mins, mins);
11330                 VectorSubtract(loc->maxs, loc->mins, size);
11331         }
11332
11333         for (i = 0;i < 6*4*3;)
11334                 for (j = 0;j < 3;j++, i++)
11335                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11336
11337         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11338         R_SetupShader_Generic_NoTexture(false, false);
11339         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11340 }
11341
11342 void R_DrawLocs(void)
11343 {
11344         int index;
11345         cl_locnode_t *loc, *nearestloc;
11346         vec3_t center;
11347         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11348         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11349         {
11350                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11351                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11352         }
11353 }
11354
11355 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11356 {
11357         if (decalsystem->decals)
11358                 Mem_Free(decalsystem->decals);
11359         memset(decalsystem, 0, sizeof(*decalsystem));
11360 }
11361
11362 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)
11363 {
11364         tridecal_t *decal;
11365         tridecal_t *decals;
11366         int i;
11367
11368         // expand or initialize the system
11369         if (decalsystem->maxdecals <= decalsystem->numdecals)
11370         {
11371                 decalsystem_t old = *decalsystem;
11372                 qboolean useshortelements;
11373                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11374                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11375                 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)));
11376                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11377                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11378                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11379                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11380                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11381                 if (decalsystem->numdecals)
11382                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11383                 if (old.decals)
11384                         Mem_Free(old.decals);
11385                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11386                         decalsystem->element3i[i] = i;
11387                 if (useshortelements)
11388                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11389                                 decalsystem->element3s[i] = i;
11390         }
11391
11392         // grab a decal and search for another free slot for the next one
11393         decals = decalsystem->decals;
11394         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11395         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11396                 ;
11397         decalsystem->freedecal = i;
11398         if (decalsystem->numdecals <= i)
11399                 decalsystem->numdecals = i + 1;
11400
11401         // initialize the decal
11402         decal->lived = 0;
11403         decal->triangleindex = triangleindex;
11404         decal->surfaceindex = surfaceindex;
11405         decal->decalsequence = decalsequence;
11406         decal->color4f[0][0] = c0[0];
11407         decal->color4f[0][1] = c0[1];
11408         decal->color4f[0][2] = c0[2];
11409         decal->color4f[0][3] = 1;
11410         decal->color4f[1][0] = c1[0];
11411         decal->color4f[1][1] = c1[1];
11412         decal->color4f[1][2] = c1[2];
11413         decal->color4f[1][3] = 1;
11414         decal->color4f[2][0] = c2[0];
11415         decal->color4f[2][1] = c2[1];
11416         decal->color4f[2][2] = c2[2];
11417         decal->color4f[2][3] = 1;
11418         decal->vertex3f[0][0] = v0[0];
11419         decal->vertex3f[0][1] = v0[1];
11420         decal->vertex3f[0][2] = v0[2];
11421         decal->vertex3f[1][0] = v1[0];
11422         decal->vertex3f[1][1] = v1[1];
11423         decal->vertex3f[1][2] = v1[2];
11424         decal->vertex3f[2][0] = v2[0];
11425         decal->vertex3f[2][1] = v2[1];
11426         decal->vertex3f[2][2] = v2[2];
11427         decal->texcoord2f[0][0] = t0[0];
11428         decal->texcoord2f[0][1] = t0[1];
11429         decal->texcoord2f[1][0] = t1[0];
11430         decal->texcoord2f[1][1] = t1[1];
11431         decal->texcoord2f[2][0] = t2[0];
11432         decal->texcoord2f[2][1] = t2[1];
11433         TriangleNormal(v0, v1, v2, decal->plane);
11434         VectorNormalize(decal->plane);
11435         decal->plane[3] = DotProduct(v0, decal->plane);
11436 }
11437
11438 extern cvar_t cl_decals_bias;
11439 extern cvar_t cl_decals_models;
11440 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11441 // baseparms, parms, temps
11442 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)
11443 {
11444         int cornerindex;
11445         int index;
11446         float v[9][3];
11447         const float *vertex3f;
11448         const float *normal3f;
11449         int numpoints;
11450         float points[2][9][3];
11451         float temp[3];
11452         float tc[9][2];
11453         float f;
11454         float c[9][4];
11455         const int *e;
11456
11457         e = rsurface.modelelement3i + 3*triangleindex;
11458
11459         vertex3f = rsurface.modelvertex3f;
11460         normal3f = rsurface.modelnormal3f;
11461
11462         if (normal3f)
11463         {
11464                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11465                 {
11466                         index = 3*e[cornerindex];
11467                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11468                 }
11469         }
11470         else
11471         {
11472                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11473                 {
11474                         index = 3*e[cornerindex];
11475                         VectorCopy(vertex3f + index, v[cornerindex]);
11476                 }
11477         }
11478
11479         // cull backfaces
11480         //TriangleNormal(v[0], v[1], v[2], normal);
11481         //if (DotProduct(normal, localnormal) < 0.0f)
11482         //      continue;
11483         // clip by each of the box planes formed from the projection matrix
11484         // if anything survives, we emit the decal
11485         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]);
11486         if (numpoints < 3)
11487                 return;
11488         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]);
11489         if (numpoints < 3)
11490                 return;
11491         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]);
11492         if (numpoints < 3)
11493                 return;
11494         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]);
11495         if (numpoints < 3)
11496                 return;
11497         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]);
11498         if (numpoints < 3)
11499                 return;
11500         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]);
11501         if (numpoints < 3)
11502                 return;
11503         // some part of the triangle survived, so we have to accept it...
11504         if (dynamic)
11505         {
11506                 // dynamic always uses the original triangle
11507                 numpoints = 3;
11508                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11509                 {
11510                         index = 3*e[cornerindex];
11511                         VectorCopy(vertex3f + index, v[cornerindex]);
11512                 }
11513         }
11514         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11515         {
11516                 // convert vertex positions to texcoords
11517                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11518                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11519                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11520                 // calculate distance fade from the projection origin
11521                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11522                 f = bound(0.0f, f, 1.0f);
11523                 c[cornerindex][0] = r * f;
11524                 c[cornerindex][1] = g * f;
11525                 c[cornerindex][2] = b * f;
11526                 c[cornerindex][3] = 1.0f;
11527                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11528         }
11529         if (dynamic)
11530                 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);
11531         else
11532                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11533                         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);
11534 }
11535 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)
11536 {
11537         matrix4x4_t projection;
11538         decalsystem_t *decalsystem;
11539         qboolean dynamic;
11540         dp_model_t *model;
11541         const msurface_t *surface;
11542         const msurface_t *surfaces;
11543         const int *surfacelist;
11544         const texture_t *texture;
11545         int numtriangles;
11546         int numsurfacelist;
11547         int surfacelistindex;
11548         int surfaceindex;
11549         int triangleindex;
11550         float localorigin[3];
11551         float localnormal[3];
11552         float localmins[3];
11553         float localmaxs[3];
11554         float localsize;
11555         //float normal[3];
11556         float planes[6][4];
11557         float angles[3];
11558         bih_t *bih;
11559         int bih_triangles_count;
11560         int bih_triangles[256];
11561         int bih_surfaces[256];
11562
11563         decalsystem = &ent->decalsystem;
11564         model = ent->model;
11565         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11566         {
11567                 R_DecalSystem_Reset(&ent->decalsystem);
11568                 return;
11569         }
11570
11571         if (!model->brush.data_leafs && !cl_decals_models.integer)
11572         {
11573                 if (decalsystem->model)
11574                         R_DecalSystem_Reset(decalsystem);
11575                 return;
11576         }
11577
11578         if (decalsystem->model != model)
11579                 R_DecalSystem_Reset(decalsystem);
11580         decalsystem->model = model;
11581
11582         RSurf_ActiveModelEntity(ent, true, false, false);
11583
11584         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11585         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11586         VectorNormalize(localnormal);
11587         localsize = worldsize*rsurface.inversematrixscale;
11588         localmins[0] = localorigin[0] - localsize;
11589         localmins[1] = localorigin[1] - localsize;
11590         localmins[2] = localorigin[2] - localsize;
11591         localmaxs[0] = localorigin[0] + localsize;
11592         localmaxs[1] = localorigin[1] + localsize;
11593         localmaxs[2] = localorigin[2] + localsize;
11594
11595         //VectorCopy(localnormal, planes[4]);
11596         //VectorVectors(planes[4], planes[2], planes[0]);
11597         AnglesFromVectors(angles, localnormal, NULL, false);
11598         AngleVectors(angles, planes[0], planes[2], planes[4]);
11599         VectorNegate(planes[0], planes[1]);
11600         VectorNegate(planes[2], planes[3]);
11601         VectorNegate(planes[4], planes[5]);
11602         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11603         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11604         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11605         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11606         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11607         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11608
11609 #if 1
11610 // works
11611 {
11612         matrix4x4_t forwardprojection;
11613         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11614         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11615 }
11616 #else
11617 // broken
11618 {
11619         float projectionvector[4][3];
11620         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11621         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11622         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11623         projectionvector[0][0] = planes[0][0] * ilocalsize;
11624         projectionvector[0][1] = planes[1][0] * ilocalsize;
11625         projectionvector[0][2] = planes[2][0] * ilocalsize;
11626         projectionvector[1][0] = planes[0][1] * ilocalsize;
11627         projectionvector[1][1] = planes[1][1] * ilocalsize;
11628         projectionvector[1][2] = planes[2][1] * ilocalsize;
11629         projectionvector[2][0] = planes[0][2] * ilocalsize;
11630         projectionvector[2][1] = planes[1][2] * ilocalsize;
11631         projectionvector[2][2] = planes[2][2] * ilocalsize;
11632         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11633         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11634         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11635         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11636 }
11637 #endif
11638
11639         dynamic = model->surfmesh.isanimated;
11640         numsurfacelist = model->nummodelsurfaces;
11641         surfacelist = model->sortedmodelsurfaces;
11642         surfaces = model->data_surfaces;
11643
11644         bih = NULL;
11645         bih_triangles_count = -1;
11646         if(!dynamic)
11647         {
11648                 if(model->render_bih.numleafs)
11649                         bih = &model->render_bih;
11650                 else if(model->collision_bih.numleafs)
11651                         bih = &model->collision_bih;
11652         }
11653         if(bih)
11654                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11655         if(bih_triangles_count == 0)
11656                 return;
11657         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11658                 return;
11659         if(bih_triangles_count > 0)
11660         {
11661                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11662                 {
11663                         surfaceindex = bih_surfaces[triangleindex];
11664                         surface = surfaces + surfaceindex;
11665                         texture = surface->texture;
11666                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11667                                 continue;
11668                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11669                                 continue;
11670                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11671                 }
11672         }
11673         else
11674         {
11675                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11676                 {
11677                         surfaceindex = surfacelist[surfacelistindex];
11678                         surface = surfaces + surfaceindex;
11679                         // check cull box first because it rejects more than any other check
11680                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11681                                 continue;
11682                         // skip transparent surfaces
11683                         texture = surface->texture;
11684                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11685                                 continue;
11686                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11687                                 continue;
11688                         numtriangles = surface->num_triangles;
11689                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11690                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11691                 }
11692         }
11693 }
11694
11695 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11696 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)
11697 {
11698         int renderentityindex;
11699         float worldmins[3];
11700         float worldmaxs[3];
11701         entity_render_t *ent;
11702
11703         if (!cl_decals_newsystem.integer)
11704                 return;
11705
11706         worldmins[0] = worldorigin[0] - worldsize;
11707         worldmins[1] = worldorigin[1] - worldsize;
11708         worldmins[2] = worldorigin[2] - worldsize;
11709         worldmaxs[0] = worldorigin[0] + worldsize;
11710         worldmaxs[1] = worldorigin[1] + worldsize;
11711         worldmaxs[2] = worldorigin[2] + worldsize;
11712
11713         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11714
11715         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11716         {
11717                 ent = r_refdef.scene.entities[renderentityindex];
11718                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11719                         continue;
11720
11721                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11722         }
11723 }
11724
11725 typedef struct r_decalsystem_splatqueue_s
11726 {
11727         vec3_t worldorigin;
11728         vec3_t worldnormal;
11729         float color[4];
11730         float tcrange[4];
11731         float worldsize;
11732         unsigned int decalsequence;
11733 }
11734 r_decalsystem_splatqueue_t;
11735
11736 int r_decalsystem_numqueued = 0;
11737 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11738
11739 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)
11740 {
11741         r_decalsystem_splatqueue_t *queue;
11742
11743         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11744                 return;
11745
11746         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11747         VectorCopy(worldorigin, queue->worldorigin);
11748         VectorCopy(worldnormal, queue->worldnormal);
11749         Vector4Set(queue->color, r, g, b, a);
11750         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11751         queue->worldsize = worldsize;
11752         queue->decalsequence = cl.decalsequence++;
11753 }
11754
11755 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11756 {
11757         int i;
11758         r_decalsystem_splatqueue_t *queue;
11759
11760         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11761                 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);
11762         r_decalsystem_numqueued = 0;
11763 }
11764
11765 extern cvar_t cl_decals_max;
11766 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11767 {
11768         int i;
11769         decalsystem_t *decalsystem = &ent->decalsystem;
11770         int numdecals;
11771         unsigned int killsequence;
11772         tridecal_t *decal;
11773         float frametime;
11774         float lifetime;
11775
11776         if (!decalsystem->numdecals)
11777                 return;
11778
11779         if (r_showsurfaces.integer)
11780                 return;
11781
11782         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11783         {
11784                 R_DecalSystem_Reset(decalsystem);
11785                 return;
11786         }
11787
11788         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11789         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11790
11791         if (decalsystem->lastupdatetime)
11792                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11793         else
11794                 frametime = 0;
11795         decalsystem->lastupdatetime = r_refdef.scene.time;
11796         numdecals = decalsystem->numdecals;
11797
11798         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11799         {
11800                 if (decal->color4f[0][3])
11801                 {
11802                         decal->lived += frametime;
11803                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11804                         {
11805                                 memset(decal, 0, sizeof(*decal));
11806                                 if (decalsystem->freedecal > i)
11807                                         decalsystem->freedecal = i;
11808                         }
11809                 }
11810         }
11811         decal = decalsystem->decals;
11812         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11813                 numdecals--;
11814
11815         // collapse the array by shuffling the tail decals into the gaps
11816         for (;;)
11817         {
11818                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11819                         decalsystem->freedecal++;
11820                 if (decalsystem->freedecal == numdecals)
11821                         break;
11822                 decal[decalsystem->freedecal] = decal[--numdecals];
11823         }
11824
11825         decalsystem->numdecals = numdecals;
11826
11827         if (numdecals <= 0)
11828         {
11829                 // if there are no decals left, reset decalsystem
11830                 R_DecalSystem_Reset(decalsystem);
11831         }
11832 }
11833
11834 extern skinframe_t *decalskinframe;
11835 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11836 {
11837         int i;
11838         decalsystem_t *decalsystem = &ent->decalsystem;
11839         int numdecals;
11840         tridecal_t *decal;
11841         float faderate;
11842         float alpha;
11843         float *v3f;
11844         float *c4f;
11845         float *t2f;
11846         const int *e;
11847         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11848         int numtris = 0;
11849
11850         numdecals = decalsystem->numdecals;
11851         if (!numdecals)
11852                 return;
11853
11854         if (r_showsurfaces.integer)
11855                 return;
11856
11857         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11858         {
11859                 R_DecalSystem_Reset(decalsystem);
11860                 return;
11861         }
11862
11863         // if the model is static it doesn't matter what value we give for
11864         // wantnormals and wanttangents, so this logic uses only rules applicable
11865         // to a model, knowing that they are meaningless otherwise
11866         RSurf_ActiveModelEntity(ent, false, false, false);
11867
11868         decalsystem->lastupdatetime = r_refdef.scene.time;
11869
11870         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11871
11872         // update vertex positions for animated models
11873         v3f = decalsystem->vertex3f;
11874         c4f = decalsystem->color4f;
11875         t2f = decalsystem->texcoord2f;
11876         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11877         {
11878                 if (!decal->color4f[0][3])
11879                         continue;
11880
11881                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11882                         continue;
11883
11884                 // skip backfaces
11885                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11886                         continue;
11887
11888                 // update color values for fading decals
11889                 if (decal->lived >= cl_decals_time.value)
11890                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11891                 else
11892                         alpha = 1.0f;
11893
11894                 c4f[ 0] = decal->color4f[0][0] * alpha;
11895                 c4f[ 1] = decal->color4f[0][1] * alpha;
11896                 c4f[ 2] = decal->color4f[0][2] * alpha;
11897                 c4f[ 3] = 1;
11898                 c4f[ 4] = decal->color4f[1][0] * alpha;
11899                 c4f[ 5] = decal->color4f[1][1] * alpha;
11900                 c4f[ 6] = decal->color4f[1][2] * alpha;
11901                 c4f[ 7] = 1;
11902                 c4f[ 8] = decal->color4f[2][0] * alpha;
11903                 c4f[ 9] = decal->color4f[2][1] * alpha;
11904                 c4f[10] = decal->color4f[2][2] * alpha;
11905                 c4f[11] = 1;
11906
11907                 t2f[0] = decal->texcoord2f[0][0];
11908                 t2f[1] = decal->texcoord2f[0][1];
11909                 t2f[2] = decal->texcoord2f[1][0];
11910                 t2f[3] = decal->texcoord2f[1][1];
11911                 t2f[4] = decal->texcoord2f[2][0];
11912                 t2f[5] = decal->texcoord2f[2][1];
11913
11914                 // update vertex positions for animated models
11915                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11916                 {
11917                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11918                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11919                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11920                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11921                 }
11922                 else
11923                 {
11924                         VectorCopy(decal->vertex3f[0], v3f);
11925                         VectorCopy(decal->vertex3f[1], v3f + 3);
11926                         VectorCopy(decal->vertex3f[2], v3f + 6);
11927                 }
11928
11929                 if (r_refdef.fogenabled)
11930                 {
11931                         alpha = RSurf_FogVertex(v3f);
11932                         VectorScale(c4f, alpha, c4f);
11933                         alpha = RSurf_FogVertex(v3f + 3);
11934                         VectorScale(c4f + 4, alpha, c4f + 4);
11935                         alpha = RSurf_FogVertex(v3f + 6);
11936                         VectorScale(c4f + 8, alpha, c4f + 8);
11937                 }
11938
11939                 v3f += 9;
11940                 c4f += 12;
11941                 t2f += 6;
11942                 numtris++;
11943         }
11944
11945         if (numtris > 0)
11946         {
11947                 r_refdef.stats[r_stat_drawndecals] += numtris;
11948
11949                 // now render the decals all at once
11950                 // (this assumes they all use one particle font texture!)
11951                 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);
11952 //              R_Mesh_ResetTextureState();
11953                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11954                 GL_DepthMask(false);
11955                 GL_DepthRange(0, 1);
11956                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11957                 GL_DepthTest(true);
11958                 GL_CullFace(GL_NONE);
11959                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11960                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11961                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11962         }
11963 }
11964
11965 static void R_DrawModelDecals(void)
11966 {
11967         int i, numdecals;
11968
11969         // fade faster when there are too many decals
11970         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11971         for (i = 0;i < r_refdef.scene.numentities;i++)
11972                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11973
11974         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11975         for (i = 0;i < r_refdef.scene.numentities;i++)
11976                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11977                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11978
11979         R_DecalSystem_ApplySplatEntitiesQueue();
11980
11981         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11982         for (i = 0;i < r_refdef.scene.numentities;i++)
11983                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11984
11985         r_refdef.stats[r_stat_totaldecals] += numdecals;
11986
11987         if (r_showsurfaces.integer)
11988                 return;
11989
11990         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11991
11992         for (i = 0;i < r_refdef.scene.numentities;i++)
11993         {
11994                 if (!r_refdef.viewcache.entityvisible[i])
11995                         continue;
11996                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11997                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11998         }
11999 }
12000
12001 extern cvar_t mod_collision_bih;
12002 static void R_DrawDebugModel(void)
12003 {
12004         entity_render_t *ent = rsurface.entity;
12005         int i, j, flagsmask;
12006         const msurface_t *surface;
12007         dp_model_t *model = ent->model;
12008
12009         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12010                 return;
12011
12012         if (r_showoverdraw.value > 0)
12013         {
12014                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12015                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12016                 R_SetupShader_Generic_NoTexture(false, false);
12017                 GL_DepthTest(false);
12018                 GL_DepthMask(false);
12019                 GL_DepthRange(0, 1);
12020                 GL_BlendFunc(GL_ONE, GL_ONE);
12021                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12022                 {
12023                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12024                                 continue;
12025                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12026                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12027                         {
12028                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12029                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12030                                 if (!rsurface.texture->currentlayers->depthmask)
12031                                         GL_Color(c, 0, 0, 1.0f);
12032                                 else if (ent == r_refdef.scene.worldentity)
12033                                         GL_Color(c, c, c, 1.0f);
12034                                 else
12035                                         GL_Color(0, c, 0, 1.0f);
12036                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12037                                 RSurf_DrawBatch();
12038                         }
12039                 }
12040                 rsurface.texture = NULL;
12041         }
12042
12043         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12044
12045 //      R_Mesh_ResetTextureState();
12046         R_SetupShader_Generic_NoTexture(false, false);
12047         GL_DepthRange(0, 1);
12048         GL_DepthTest(!r_showdisabledepthtest.integer);
12049         GL_DepthMask(false);
12050         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12051
12052         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12053         {
12054                 int triangleindex;
12055                 int bihleafindex;
12056                 qboolean cullbox = false;
12057                 const q3mbrush_t *brush;
12058                 const bih_t *bih = &model->collision_bih;
12059                 const bih_leaf_t *bihleaf;
12060                 float vertex3f[3][3];
12061                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12062                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12063                 {
12064                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12065                                 continue;
12066                         switch (bihleaf->type)
12067                         {
12068                         case BIH_BRUSH:
12069                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12070                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12071                                 {
12072                                         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);
12073                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12074                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12075                                 }
12076                                 break;
12077                         case BIH_COLLISIONTRIANGLE:
12078                                 triangleindex = bihleaf->itemindex;
12079                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12080                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12081                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12082                                 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);
12083                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12084                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12085                                 break;
12086                         case BIH_RENDERTRIANGLE:
12087                                 triangleindex = bihleaf->itemindex;
12088                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12089                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12090                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12091                                 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);
12092                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12093                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12094                                 break;
12095                         }
12096                 }
12097         }
12098
12099         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12100
12101 #ifndef USE_GLES2
12102         if (r_showtris.integer && qglPolygonMode)
12103         {
12104                 if (r_showdisabledepthtest.integer)
12105                 {
12106                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12107                         GL_DepthMask(false);
12108                 }
12109                 else
12110                 {
12111                         GL_BlendFunc(GL_ONE, GL_ZERO);
12112                         GL_DepthMask(true);
12113                 }
12114                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12115                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12116                 {
12117                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12118                                 continue;
12119                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12120                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12121                         {
12122                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12123                                 if (!rsurface.texture->currentlayers->depthmask)
12124                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12125                                 else if (ent == r_refdef.scene.worldentity)
12126                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12127                                 else
12128                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12129                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12130                                 RSurf_DrawBatch();
12131                         }
12132                 }
12133                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12134                 rsurface.texture = NULL;
12135         }
12136
12137         if (r_shownormals.value != 0 && qglBegin)
12138         {
12139                 int l, k;
12140                 vec3_t v;
12141                 if (r_showdisabledepthtest.integer)
12142                 {
12143                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12144                         GL_DepthMask(false);
12145                 }
12146                 else
12147                 {
12148                         GL_BlendFunc(GL_ONE, GL_ZERO);
12149                         GL_DepthMask(true);
12150                 }
12151                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12152                 {
12153                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12154                                 continue;
12155                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12156                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12157                         {
12158                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12159                                 qglBegin(GL_LINES);
12160                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12161                                 {
12162                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12163                                         {
12164                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12165                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12166                                                 qglVertex3f(v[0], v[1], v[2]);
12167                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12168                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12169                                                 qglVertex3f(v[0], v[1], v[2]);
12170                                         }
12171                                 }
12172                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12173                                 {
12174                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12175                                         {
12176                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12177                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12178                                                 qglVertex3f(v[0], v[1], v[2]);
12179                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12180                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12181                                                 qglVertex3f(v[0], v[1], v[2]);
12182                                         }
12183                                 }
12184                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12185                                 {
12186                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12187                                         {
12188                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12189                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12190                                                 qglVertex3f(v[0], v[1], v[2]);
12191                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12192                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12193                                                 qglVertex3f(v[0], v[1], v[2]);
12194                                         }
12195                                 }
12196                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12197                                 {
12198                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12199                                         {
12200                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12201                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12202                                                 qglVertex3f(v[0], v[1], v[2]);
12203                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12204                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12205                                                 qglVertex3f(v[0], v[1], v[2]);
12206                                         }
12207                                 }
12208                                 qglEnd();
12209                                 CHECKGLERROR
12210                         }
12211                 }
12212                 rsurface.texture = NULL;
12213         }
12214 #endif
12215 }
12216
12217 int r_maxsurfacelist = 0;
12218 const msurface_t **r_surfacelist = NULL;
12219 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12220 {
12221         int i, j, endj, flagsmask;
12222         dp_model_t *model = ent->model;
12223         msurface_t *surfaces;
12224         unsigned char *update;
12225         int numsurfacelist = 0;
12226         if (model == NULL)
12227                 return;
12228
12229         if (r_maxsurfacelist < model->num_surfaces)
12230         {
12231                 r_maxsurfacelist = model->num_surfaces;
12232                 if (r_surfacelist)
12233                         Mem_Free((msurface_t **)r_surfacelist);
12234                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12235         }
12236
12237         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12238                 RSurf_ActiveModelEntity(ent, false, false, false);
12239         else if (prepass)
12240                 RSurf_ActiveModelEntity(ent, true, true, true);
12241         else if (depthonly)
12242         {
12243                 switch (vid.renderpath)
12244                 {
12245                 case RENDERPATH_GL20:
12246                 case RENDERPATH_D3D9:
12247                 case RENDERPATH_D3D10:
12248                 case RENDERPATH_D3D11:
12249                 case RENDERPATH_SOFT:
12250                 case RENDERPATH_GLES2:
12251                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12252                         break;
12253                 case RENDERPATH_GL11:
12254                 case RENDERPATH_GL13:
12255                 case RENDERPATH_GLES1:
12256                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12257                         break;
12258                 }
12259         }
12260         else
12261         {
12262                 switch (vid.renderpath)
12263                 {
12264                 case RENDERPATH_GL20:
12265                 case RENDERPATH_D3D9:
12266                 case RENDERPATH_D3D10:
12267                 case RENDERPATH_D3D11:
12268                 case RENDERPATH_SOFT:
12269                 case RENDERPATH_GLES2:
12270                         RSurf_ActiveModelEntity(ent, true, true, false);
12271                         break;
12272                 case RENDERPATH_GL11:
12273                 case RENDERPATH_GL13:
12274                 case RENDERPATH_GLES1:
12275                         RSurf_ActiveModelEntity(ent, true, false, false);
12276                         break;
12277                 }
12278         }
12279
12280         surfaces = model->data_surfaces;
12281         update = model->brushq1.lightmapupdateflags;
12282
12283         // update light styles
12284         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12285         {
12286                 model_brush_lightstyleinfo_t *style;
12287                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12288                 {
12289                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12290                         {
12291                                 int *list = style->surfacelist;
12292                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12293                                 for (j = 0;j < style->numsurfaces;j++)
12294                                         update[list[j]] = true;
12295                         }
12296                 }
12297         }
12298
12299         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12300
12301         if (debug)
12302         {
12303                 R_DrawDebugModel();
12304                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12305                 return;
12306         }
12307
12308         rsurface.lightmaptexture = NULL;
12309         rsurface.deluxemaptexture = NULL;
12310         rsurface.uselightmaptexture = false;
12311         rsurface.texture = NULL;
12312         rsurface.rtlight = NULL;
12313         numsurfacelist = 0;
12314         // add visible surfaces to draw list
12315         if (ent == r_refdef.scene.worldentity)
12316         {
12317                 // for the world entity, check surfacevisible
12318                 for (i = 0;i < model->nummodelsurfaces;i++)
12319                 {
12320                         j = model->sortedmodelsurfaces[i];
12321                         if (r_refdef.viewcache.world_surfacevisible[j])
12322                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12323                 }
12324         }
12325         else
12326         {
12327                 // add all surfaces
12328                 for (i = 0; i < model->nummodelsurfaces; i++)
12329                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12330         }
12331         // don't do anything if there were no surfaces
12332         if (!numsurfacelist)
12333         {
12334                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12335                 return;
12336         }
12337         // update lightmaps if needed
12338         if (update)
12339         {
12340                 int updated = 0;
12341                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12342                 {
12343                         if (update[j])
12344                         {
12345                                 updated++;
12346                                 R_BuildLightMap(ent, surfaces + j);
12347                         }
12348                 }
12349         }
12350
12351         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12352
12353         // add to stats if desired
12354         if (r_speeds.integer && !skysurfaces && !depthonly)
12355         {
12356                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12357                 for (j = 0;j < numsurfacelist;j++)
12358                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12359         }
12360
12361         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12362 }
12363
12364 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12365 {
12366         int q;
12367         static texture_t texture;
12368         static msurface_t surface;
12369         const msurface_t *surfacelist = &surface;
12370
12371         // fake enough texture and surface state to render this geometry
12372
12373         texture.update_lastrenderframe = -1; // regenerate this texture
12374         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12375         texture.basealpha = 1.0f;
12376         texture.currentskinframe = skinframe;
12377         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12378         texture.offsetmapping = OFFSETMAPPING_OFF;
12379         texture.offsetscale = 1;
12380         texture.specularscalemod = 1;
12381         texture.specularpowermod = 1;
12382         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12383         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12384         // JUST GREP FOR "specularscalemod = 1".
12385
12386         for (q = 0; q < 3; q++)
12387         {
12388                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12389                 texture.render_modellight_lightdir[q] = q == 2;
12390                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12391                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12392                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12393                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12394                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12395                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12396                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12397                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12398         }
12399         texture.currentalpha = 1.0f;
12400
12401         surface.texture = &texture;
12402         surface.num_triangles = numtriangles;
12403         surface.num_firsttriangle = firsttriangle;
12404         surface.num_vertices = numvertices;
12405         surface.num_firstvertex = firstvertex;
12406
12407         // now render it
12408         rsurface.texture = R_GetCurrentTexture(surface.texture);
12409         rsurface.lightmaptexture = NULL;
12410         rsurface.deluxemaptexture = NULL;
12411         rsurface.uselightmaptexture = false;
12412         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12413 }
12414
12415 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)
12416 {
12417         static msurface_t surface;
12418         const msurface_t *surfacelist = &surface;
12419
12420         // fake enough texture and surface state to render this geometry
12421         surface.texture = texture;
12422         surface.num_triangles = numtriangles;
12423         surface.num_firsttriangle = firsttriangle;
12424         surface.num_vertices = numvertices;
12425         surface.num_firstvertex = firstvertex;
12426
12427         // now render it
12428         rsurface.texture = R_GetCurrentTexture(surface.texture);
12429         rsurface.lightmaptexture = NULL;
12430         rsurface.deluxemaptexture = NULL;
12431         rsurface.uselightmaptexture = false;
12432         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12433 }