]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Cvar onChange for qc menu for stable branch
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
73 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
74 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
75 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
76 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84
85 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
93 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
94 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
98 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
105 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
106 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
116 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
132 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
133
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
145 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
159 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
160
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169
170 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
171 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
172
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176
177 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
178 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
179 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
183 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
184 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
196 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
199 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
200 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
201 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
202 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
203 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
204 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
205 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
206
207 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
208 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
215 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
216 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
217
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243
244 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
245
246 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
247
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251
252 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
253 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
259
260 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
261
262 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {
265         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
269 };
270
271 extern cvar_t v_glslgamma_2d;
272
273 extern qboolean v_flipped_state;
274
275 r_framebufferstate_t r_fb;
276
277 /// shadow volume bsp struct with automatically growing nodes buffer
278 svbsp_t r_svbsp;
279
280 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
281
282 rtexture_t *r_texture_blanknormalmap;
283 rtexture_t *r_texture_white;
284 rtexture_t *r_texture_grey128;
285 rtexture_t *r_texture_black;
286 rtexture_t *r_texture_notexture;
287 rtexture_t *r_texture_whitecube;
288 rtexture_t *r_texture_normalizationcube;
289 rtexture_t *r_texture_fogattenuation;
290 rtexture_t *r_texture_fogheighttexture;
291 rtexture_t *r_texture_gammaramps;
292 unsigned int r_texture_gammaramps_serial;
293 //rtexture_t *r_texture_fogintensity;
294 rtexture_t *r_texture_reflectcube;
295
296 // TODO: hash lookups?
297 typedef struct cubemapinfo_s
298 {
299         char basename[64];
300         rtexture_t *texture;
301 }
302 cubemapinfo_t;
303
304 int r_texture_numcubemaps;
305 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
306
307 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
308 unsigned int r_numqueries;
309 unsigned int r_maxqueries;
310
311 typedef struct r_qwskincache_s
312 {
313         char name[MAX_QPATH];
314         skinframe_t *skinframe;
315 }
316 r_qwskincache_t;
317
318 static r_qwskincache_t *r_qwskincache;
319 static int r_qwskincache_size;
320
321 /// vertex coordinates for a quad that covers the screen exactly
322 extern const float r_screenvertex3f[12];
323 extern const float r_d3dscreenvertex3f[12];
324 const float r_screenvertex3f[12] =
325 {
326         0, 0, 0,
327         1, 0, 0,
328         1, 1, 0,
329         0, 1, 0
330 };
331 const float r_d3dscreenvertex3f[12] =
332 {
333         0, 1, 0,
334         1, 1, 0,
335         1, 0, 0,
336         0, 0, 0
337 };
338
339 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
340 {
341         int i;
342         for (i = 0;i < verts;i++)
343         {
344                 out[0] = in[0] * r;
345                 out[1] = in[1] * g;
346                 out[2] = in[2] * b;
347                 out[3] = in[3];
348                 in += 4;
349                 out += 4;
350         }
351 }
352
353 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
354 {
355         int i;
356         for (i = 0;i < verts;i++)
357         {
358                 out[0] = r;
359                 out[1] = g;
360                 out[2] = b;
361                 out[3] = a;
362                 out += 4;
363         }
364 }
365
366 // FIXME: move this to client?
367 void FOG_clear(void)
368 {
369         if (gamemode == GAME_NEHAHRA)
370         {
371                 Cvar_Set("gl_fogenable", "0");
372                 Cvar_Set("gl_fogdensity", "0.2");
373                 Cvar_Set("gl_fogred", "0.3");
374                 Cvar_Set("gl_foggreen", "0.3");
375                 Cvar_Set("gl_fogblue", "0.3");
376         }
377         r_refdef.fog_density = 0;
378         r_refdef.fog_red = 0;
379         r_refdef.fog_green = 0;
380         r_refdef.fog_blue = 0;
381         r_refdef.fog_alpha = 1;
382         r_refdef.fog_start = 0;
383         r_refdef.fog_end = 16384;
384         r_refdef.fog_height = 1<<30;
385         r_refdef.fog_fadedepth = 128;
386         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
387 }
388
389 static void R_BuildBlankTextures(void)
390 {
391         unsigned char data[4];
392         data[2] = 128; // normal X
393         data[1] = 128; // normal Y
394         data[0] = 255; // normal Z
395         data[3] = 255; // height
396         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 255;
398         data[1] = 255;
399         data[2] = 255;
400         data[3] = 255;
401         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 128;
403         data[1] = 128;
404         data[2] = 128;
405         data[3] = 255;
406         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407         data[0] = 0;
408         data[1] = 0;
409         data[2] = 0;
410         data[3] = 255;
411         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
412 }
413
414 static void R_BuildNoTexture(void)
415 {
416         int x, y;
417         unsigned char pix[16][16][4];
418         // this makes a light grey/dark grey checkerboard texture
419         for (y = 0;y < 16;y++)
420         {
421                 for (x = 0;x < 16;x++)
422                 {
423                         if ((y < 8) ^ (x < 8))
424                         {
425                                 pix[y][x][0] = 128;
426                                 pix[y][x][1] = 128;
427                                 pix[y][x][2] = 128;
428                                 pix[y][x][3] = 255;
429                         }
430                         else
431                         {
432                                 pix[y][x][0] = 64;
433                                 pix[y][x][1] = 64;
434                                 pix[y][x][2] = 64;
435                                 pix[y][x][3] = 255;
436                         }
437                 }
438         }
439         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
440 }
441
442 static void R_BuildWhiteCube(void)
443 {
444         unsigned char data[6*1*1*4];
445         memset(data, 255, sizeof(data));
446         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
447 }
448
449 static void R_BuildNormalizationCube(void)
450 {
451         int x, y, side;
452         vec3_t v;
453         vec_t s, t, intensity;
454 #define NORMSIZE 64
455         unsigned char *data;
456         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
457         for (side = 0;side < 6;side++)
458         {
459                 for (y = 0;y < NORMSIZE;y++)
460                 {
461                         for (x = 0;x < NORMSIZE;x++)
462                         {
463                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 switch(side)
466                                 {
467                                 default:
468                                 case 0:
469                                         v[0] = 1;
470                                         v[1] = -t;
471                                         v[2] = -s;
472                                         break;
473                                 case 1:
474                                         v[0] = -1;
475                                         v[1] = -t;
476                                         v[2] = s;
477                                         break;
478                                 case 2:
479                                         v[0] = s;
480                                         v[1] = 1;
481                                         v[2] = t;
482                                         break;
483                                 case 3:
484                                         v[0] = s;
485                                         v[1] = -1;
486                                         v[2] = -t;
487                                         break;
488                                 case 4:
489                                         v[0] = s;
490                                         v[1] = -t;
491                                         v[2] = 1;
492                                         break;
493                                 case 5:
494                                         v[0] = -s;
495                                         v[1] = -t;
496                                         v[2] = -1;
497                                         break;
498                                 }
499                                 intensity = 127.0f / sqrt(DotProduct(v, v));
500                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
501                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
502                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
503                                 data[((side*64+y)*64+x)*4+3] = 255;
504                         }
505                 }
506         }
507         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508         Mem_Free(data);
509 }
510
511 static void R_BuildFogTexture(void)
512 {
513         int x, b;
514 #define FOGWIDTH 256
515         unsigned char data1[FOGWIDTH][4];
516         //unsigned char data2[FOGWIDTH][4];
517         double d, r, alpha;
518
519         r_refdef.fogmasktable_start = r_refdef.fog_start;
520         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
521         r_refdef.fogmasktable_range = r_refdef.fogrange;
522         r_refdef.fogmasktable_density = r_refdef.fog_density;
523
524         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
525         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
526         {
527                 d = (x * r - r_refdef.fogmasktable_start);
528                 if(developer_extra.integer)
529                         Con_DPrintf("%f ", d);
530                 d = max(0, d);
531                 if (r_fog_exp2.integer)
532                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
533                 else
534                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
535                 if(developer_extra.integer)
536                         Con_DPrintf(" : %f ", alpha);
537                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
538                 if(developer_extra.integer)
539                         Con_DPrintf(" = %f\n", alpha);
540                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
541         }
542
543         for (x = 0;x < FOGWIDTH;x++)
544         {
545                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
546                 data1[x][0] = b;
547                 data1[x][1] = b;
548                 data1[x][2] = b;
549                 data1[x][3] = 255;
550                 //data2[x][0] = 255 - b;
551                 //data2[x][1] = 255 - b;
552                 //data2[x][2] = 255 - b;
553                 //data2[x][3] = 255;
554         }
555         if (r_texture_fogattenuation)
556         {
557                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559         }
560         else
561         {
562                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
563                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
564         }
565 }
566
567 static void R_BuildFogHeightTexture(void)
568 {
569         unsigned char *inpixels;
570         int size;
571         int x;
572         int y;
573         int j;
574         float c[4];
575         float f;
576         inpixels = NULL;
577         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
578         if (r_refdef.fogheighttexturename[0])
579                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
580         if (!inpixels)
581         {
582                 r_refdef.fog_height_tablesize = 0;
583                 if (r_texture_fogheighttexture)
584                         R_FreeTexture(r_texture_fogheighttexture);
585                 r_texture_fogheighttexture = NULL;
586                 if (r_refdef.fog_height_table2d)
587                         Mem_Free(r_refdef.fog_height_table2d);
588                 r_refdef.fog_height_table2d = NULL;
589                 if (r_refdef.fog_height_table1d)
590                         Mem_Free(r_refdef.fog_height_table1d);
591                 r_refdef.fog_height_table1d = NULL;
592                 return;
593         }
594         size = image_width;
595         r_refdef.fog_height_tablesize = size;
596         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
597         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
598         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
599         Mem_Free(inpixels);
600         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
601         // average fog color table accounting for every fog layer between a point
602         // and the camera.  (Note: attenuation is handled separately!)
603         for (y = 0;y < size;y++)
604         {
605                 for (x = 0;x < size;x++)
606                 {
607                         Vector4Clear(c);
608                         f = 0;
609                         if (x < y)
610                         {
611                                 for (j = x;j <= y;j++)
612                                 {
613                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
614                                         f++;
615                                 }
616                         }
617                         else
618                         {
619                                 for (j = x;j >= y;j--)
620                                 {
621                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
622                                         f++;
623                                 }
624                         }
625                         f = 1.0f / f;
626                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
627                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
630                 }
631         }
632         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
633 }
634
635 //=======================================================================================================================================================
636
637 static const char *builtinshaderstrings[] =
638 {
639 #include "shader_glsl.h"
640 0
641 };
642
643 const char *builtinhlslshaderstrings[] =
644 {
645 #include "shader_hlsl.h"
646 0
647 };
648
649 //=======================================================================================================================================================
650
651 typedef struct shaderpermutationinfo_s
652 {
653         const char *pretext;
654         const char *name;
655 }
656 shaderpermutationinfo_t;
657
658 typedef struct shadermodeinfo_s
659 {
660         const char *sourcebasename;
661         const char *extension;
662         const char **builtinshaderstrings;
663         const char *pretext;
664         const char *name;
665         char *filename;
666         char *builtinstring;
667         int builtincrc;
668 }
669 shadermodeinfo_t;
670
671 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
672 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
673 {
674         {"#define USEDIFFUSE\n", " diffuse"},
675         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
676         {"#define USEVIEWTINT\n", " viewtint"},
677         {"#define USECOLORMAPPING\n", " colormapping"},
678         {"#define USESATURATION\n", " saturation"},
679         {"#define USEFOGINSIDE\n", " foginside"},
680         {"#define USEFOGOUTSIDE\n", " fogoutside"},
681         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
682         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
683         {"#define USEGAMMARAMPS\n", " gammaramps"},
684         {"#define USECUBEFILTER\n", " cubefilter"},
685         {"#define USEGLOW\n", " glow"},
686         {"#define USEBLOOM\n", " bloom"},
687         {"#define USESPECULAR\n", " specular"},
688         {"#define USEPOSTPROCESSING\n", " postprocessing"},
689         {"#define USEREFLECTION\n", " reflection"},
690         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
691         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
692         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
693         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
694         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
695         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
696         {"#define USEALPHAKILL\n", " alphakill"},
697         {"#define USEREFLECTCUBE\n", " reflectcube"},
698         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
699         {"#define USEBOUNCEGRID\n", " bouncegrid"},
700         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
701         {"#define USETRIPPY\n", " trippy"},
702         {"#define USEDEPTHRGB\n", " depthrgb"},
703         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
704         {"#define USESKELETAL\n", " skeletal"},
705         {"#define USEOCCLUDE\n", " occlude"}
706 };
707
708 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
709 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
710 {
711         // SHADERLANGUAGE_GLSL
712         {
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730         },
731         // SHADERLANGUAGE_HLSL
732         {
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
750         },
751 };
752
753 struct r_glsl_permutation_s;
754 typedef struct r_glsl_permutation_s
755 {
756         /// hash lookup data
757         struct r_glsl_permutation_s *hashnext;
758         unsigned int mode;
759         dpuint64 permutation;
760
761         /// indicates if we have tried compiling this permutation already
762         qboolean compiled;
763         /// 0 if compilation failed
764         int program;
765         // texture units assigned to each detected uniform
766         int tex_Texture_First;
767         int tex_Texture_Second;
768         int tex_Texture_GammaRamps;
769         int tex_Texture_Normal;
770         int tex_Texture_Color;
771         int tex_Texture_Gloss;
772         int tex_Texture_Glow;
773         int tex_Texture_SecondaryNormal;
774         int tex_Texture_SecondaryColor;
775         int tex_Texture_SecondaryGloss;
776         int tex_Texture_SecondaryGlow;
777         int tex_Texture_Pants;
778         int tex_Texture_Shirt;
779         int tex_Texture_FogHeightTexture;
780         int tex_Texture_FogMask;
781         int tex_Texture_Lightmap;
782         int tex_Texture_Deluxemap;
783         int tex_Texture_Attenuation;
784         int tex_Texture_Cube;
785         int tex_Texture_Refraction;
786         int tex_Texture_Reflection;
787         int tex_Texture_ShadowMap2D;
788         int tex_Texture_CubeProjection;
789         int tex_Texture_ScreenNormalMap;
790         int tex_Texture_ScreenDiffuse;
791         int tex_Texture_ScreenSpecular;
792         int tex_Texture_ReflectMask;
793         int tex_Texture_ReflectCube;
794         int tex_Texture_BounceGrid;
795         /// locations of detected uniforms in program object, or -1 if not found
796         int loc_Texture_First;
797         int loc_Texture_Second;
798         int loc_Texture_GammaRamps;
799         int loc_Texture_Normal;
800         int loc_Texture_Color;
801         int loc_Texture_Gloss;
802         int loc_Texture_Glow;
803         int loc_Texture_SecondaryNormal;
804         int loc_Texture_SecondaryColor;
805         int loc_Texture_SecondaryGloss;
806         int loc_Texture_SecondaryGlow;
807         int loc_Texture_Pants;
808         int loc_Texture_Shirt;
809         int loc_Texture_FogHeightTexture;
810         int loc_Texture_FogMask;
811         int loc_Texture_Lightmap;
812         int loc_Texture_Deluxemap;
813         int loc_Texture_Attenuation;
814         int loc_Texture_Cube;
815         int loc_Texture_Refraction;
816         int loc_Texture_Reflection;
817         int loc_Texture_ShadowMap2D;
818         int loc_Texture_CubeProjection;
819         int loc_Texture_ScreenNormalMap;
820         int loc_Texture_ScreenDiffuse;
821         int loc_Texture_ScreenSpecular;
822         int loc_Texture_ReflectMask;
823         int loc_Texture_ReflectCube;
824         int loc_Texture_BounceGrid;
825         int loc_Alpha;
826         int loc_BloomBlur_Parameters;
827         int loc_ClientTime;
828         int loc_Color_Ambient;
829         int loc_Color_Diffuse;
830         int loc_Color_Specular;
831         int loc_Color_Glow;
832         int loc_Color_Pants;
833         int loc_Color_Shirt;
834         int loc_DeferredColor_Ambient;
835         int loc_DeferredColor_Diffuse;
836         int loc_DeferredColor_Specular;
837         int loc_DeferredMod_Diffuse;
838         int loc_DeferredMod_Specular;
839         int loc_DistortScaleRefractReflect;
840         int loc_EyePosition;
841         int loc_FogColor;
842         int loc_FogHeightFade;
843         int loc_FogPlane;
844         int loc_FogPlaneViewDist;
845         int loc_FogRangeRecip;
846         int loc_LightColor;
847         int loc_LightDir;
848         int loc_LightPosition;
849         int loc_OffsetMapping_ScaleSteps;
850         int loc_OffsetMapping_LodDistance;
851         int loc_OffsetMapping_Bias;
852         int loc_PixelSize;
853         int loc_ReflectColor;
854         int loc_ReflectFactor;
855         int loc_ReflectOffset;
856         int loc_RefractColor;
857         int loc_Saturation;
858         int loc_ScreenCenterRefractReflect;
859         int loc_ScreenScaleRefractReflect;
860         int loc_ScreenToDepth;
861         int loc_ShadowMap_Parameters;
862         int loc_ShadowMap_TextureScale;
863         int loc_SpecularPower;
864         int loc_Skeletal_Transform12;
865         int loc_UserVec1;
866         int loc_UserVec2;
867         int loc_UserVec3;
868         int loc_UserVec4;
869         int loc_ViewTintColor;
870         int loc_ViewToLight;
871         int loc_ModelToLight;
872         int loc_TexMatrix;
873         int loc_BackgroundTexMatrix;
874         int loc_ModelViewProjectionMatrix;
875         int loc_ModelViewMatrix;
876         int loc_PixelToScreenTexCoord;
877         int loc_ModelToReflectCube;
878         int loc_ShadowMapMatrix;
879         int loc_BloomColorSubtract;
880         int loc_NormalmapScrollBlend;
881         int loc_BounceGridMatrix;
882         int loc_BounceGridIntensity;
883         /// uniform block bindings
884         int ubibind_Skeletal_Transform12_UniformBlock;
885         /// uniform block indices
886         int ubiloc_Skeletal_Transform12_UniformBlock;
887 }
888 r_glsl_permutation_t;
889
890 #define SHADERPERMUTATION_HASHSIZE 256
891
892
893 // non-degradable "lightweight" shader parameters to keep the permutations simpler
894 // these can NOT degrade! only use for simple stuff
895 enum
896 {
897         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
898         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
899         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
900         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
903         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
904         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
905         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
906         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
907         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
908         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
909         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
910         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
911 };
912 #define SHADERSTATICPARMS_COUNT 14
913
914 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
915 static int shaderstaticparms_count = 0;
916
917 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
918 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
919
920 extern qboolean r_shadow_shadowmapsampler;
921 extern int r_shadow_shadowmappcf;
922 qboolean R_CompileShader_CheckStaticParms(void)
923 {
924         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
925         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
926         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
927
928         // detect all
929         if (r_glsl_saturation_redcompensate.integer)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
931         if (r_glsl_vertextextureblend_usebothalphas.integer)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
933         if (r_shadow_glossexact.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
935         if (r_glsl_postprocess.integer)
936         {
937                 if (r_glsl_postprocess_uservec1_enable.integer)
938                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
939                 if (r_glsl_postprocess_uservec2_enable.integer)
940                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
941                 if (r_glsl_postprocess_uservec3_enable.integer)
942                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
943                 if (r_glsl_postprocess_uservec4_enable.integer)
944                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
945         }
946         if (r_fxaa.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
948         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
950
951         if (r_shadow_shadowmapsampler)
952                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
953         if (r_shadow_shadowmappcf > 1)
954                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
955         else if (r_shadow_shadowmappcf)
956                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
957         if (r_celshading.integer)
958                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
959         if (r_celoutlines.integer)
960                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
961
962         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
963 }
964
965 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
966         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
967                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
968         else \
969                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
970 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
971 {
972         shaderstaticparms_count = 0;
973
974         // emit all
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
989 }
990
991 /// information about each possible shader permutation
992 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
993 /// currently selected permutation
994 r_glsl_permutation_t *r_glsl_permutation;
995 /// storage for permutations linked in the hash table
996 memexpandablearray_t r_glsl_permutationarray;
997
998 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
999 {
1000         //unsigned int hashdepth = 0;
1001         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1002         r_glsl_permutation_t *p;
1003         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1004         {
1005                 if (p->mode == mode && p->permutation == permutation)
1006                 {
1007                         //if (hashdepth > 10)
1008                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1009                         return p;
1010                 }
1011                 //hashdepth++;
1012         }
1013         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1014         p->mode = mode;
1015         p->permutation = permutation;
1016         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1017         r_glsl_permutationhash[mode][hashindex] = p;
1018         //if (hashdepth > 10)
1019         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1020         return p;
1021 }
1022
1023 static char *R_ShaderStrCat(const char **strings)
1024 {
1025         char *string, *s;
1026         const char **p = strings;
1027         const char *t;
1028         size_t len = 0;
1029         for (p = strings;(t = *p);p++)
1030                 len += strlen(t);
1031         len++;
1032         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1033         len = 0;
1034         for (p = strings;(t = *p);p++)
1035         {
1036                 len = strlen(t);
1037                 memcpy(s, t, len);
1038                 s += len;
1039         }
1040         *s = 0;
1041         return string;
1042 }
1043
1044 static char *R_ShaderStrCat(const char **strings);
1045 static void R_InitShaderModeInfo(void)
1046 {
1047         int i, language;
1048         shadermodeinfo_t *modeinfo;
1049         // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1050         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1051         {
1052                 for (i = 0; i < SHADERMODE_COUNT; i++)
1053                 {
1054                         char filename[MAX_QPATH];
1055                         modeinfo = &shadermodeinfo[language][i];
1056                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1057                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1058                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1059                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1060                 }
1061         }
1062 }
1063
1064 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1065 {
1066         char *shaderstring;
1067         // if the mode has no filename we have to return the builtin string
1068         if (builtinonly || !modeinfo->filename)
1069                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1070         // note that FS_LoadFile appends a 0 byte to make it a valid string
1071         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1072         if (shaderstring)
1073         {
1074                 if (printfromdisknotice)
1075                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1076                 return shaderstring;
1077         }
1078         // fall back to builtinstring
1079         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127         // if we can do #version 120, we should (this adds the invariant keyword)
1128         else if(vid.support.glshaderversion >= 120)
1129         {
1130                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1131                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1132                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1133                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1134                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1135                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1136         }
1137         // GLES also adds several things from GLSL120
1138         switch(vid.renderpath)
1139         {
1140         case RENDERPATH_GLES2:
1141                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1142                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1143                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1144                 break;
1145         default:
1146                 break;
1147         }
1148
1149         // the first pretext is which type of shader to compile as
1150         // (later these will all be bound together as a program object)
1151         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1152         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1153         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1154
1155         // the second pretext is the mode (for example a light source)
1156         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1157         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1158         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1159         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1160
1161         // now add all the permutation pretexts
1162         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1163         {
1164                 if (permutation & (1ll<<i))
1165                 {
1166                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1167                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1170                 }
1171                 else
1172                 {
1173                         // keep line numbers correct
1174                         vertstrings_list[vertstrings_count++] = "\n";
1175                         geomstrings_list[geomstrings_count++] = "\n";
1176                         fragstrings_list[fragstrings_count++] = "\n";
1177                 }
1178         }
1179
1180         // add static parms
1181         R_CompileShader_AddStaticParms(mode, permutation);
1182         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1183         vertstrings_count += shaderstaticparms_count;
1184         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1185         geomstrings_count += shaderstaticparms_count;
1186         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1187         fragstrings_count += shaderstaticparms_count;
1188
1189         // now append the shader text itself
1190         vertstrings_list[vertstrings_count++] = sourcestring;
1191         geomstrings_list[geomstrings_count++] = sourcestring;
1192         fragstrings_list[fragstrings_count++] = sourcestring;
1193
1194         // compile the shader program
1195         if (vertstrings_count + geomstrings_count + fragstrings_count)
1196                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1197         if (p->program)
1198         {
1199                 CHECKGLERROR
1200                 qglUseProgram(p->program);CHECKGLERROR
1201                 // look up all the uniform variable names we care about, so we don't
1202                 // have to look them up every time we set them
1203
1204 #if 0
1205                 // debugging aid
1206                 {
1207                         GLint activeuniformindex = 0;
1208                         GLint numactiveuniforms = 0;
1209                         char uniformname[128];
1210                         GLsizei uniformnamelength = 0;
1211                         GLint uniformsize = 0;
1212                         GLenum uniformtype = 0;
1213                         memset(uniformname, 0, sizeof(uniformname));
1214                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1215                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1216                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1217                         {
1218                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1219                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1220                         }
1221                 }
1222 #endif
1223
1224                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1225                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1226                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1227                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1228                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1229                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1230                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1231                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1232                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1233                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1234                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1235                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1236                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1237                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1238                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1239                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1240                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1241                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1242                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1243                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1244                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1245                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1246                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1247                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1248                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1249                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1250                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1251                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1252                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1253                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1254                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1255                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1256                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1257                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1258                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1259                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1260                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1261                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1262                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1263                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1264                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1265                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1266                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1267                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1268                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1269                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1270                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1271                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1272                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1273                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1274                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1275                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1276                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1277                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1278                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1279                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1280                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1281                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1282                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1283                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1284                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1285                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1286                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1287                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1288                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1289                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1290                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1291                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1292                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1293                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1294                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1295                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1296                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1297                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1298                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1299                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1300                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1301                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1302                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1303                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1304                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1305                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1306                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1307                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1308                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1309                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1310                 // initialize the samplers to refer to the texture units we use
1311                 p->tex_Texture_First = -1;
1312                 p->tex_Texture_Second = -1;
1313                 p->tex_Texture_GammaRamps = -1;
1314                 p->tex_Texture_Normal = -1;
1315                 p->tex_Texture_Color = -1;
1316                 p->tex_Texture_Gloss = -1;
1317                 p->tex_Texture_Glow = -1;
1318                 p->tex_Texture_SecondaryNormal = -1;
1319                 p->tex_Texture_SecondaryColor = -1;
1320                 p->tex_Texture_SecondaryGloss = -1;
1321                 p->tex_Texture_SecondaryGlow = -1;
1322                 p->tex_Texture_Pants = -1;
1323                 p->tex_Texture_Shirt = -1;
1324                 p->tex_Texture_FogHeightTexture = -1;
1325                 p->tex_Texture_FogMask = -1;
1326                 p->tex_Texture_Lightmap = -1;
1327                 p->tex_Texture_Deluxemap = -1;
1328                 p->tex_Texture_Attenuation = -1;
1329                 p->tex_Texture_Cube = -1;
1330                 p->tex_Texture_Refraction = -1;
1331                 p->tex_Texture_Reflection = -1;
1332                 p->tex_Texture_ShadowMap2D = -1;
1333                 p->tex_Texture_CubeProjection = -1;
1334                 p->tex_Texture_ScreenNormalMap = -1;
1335                 p->tex_Texture_ScreenDiffuse = -1;
1336                 p->tex_Texture_ScreenSpecular = -1;
1337                 p->tex_Texture_ReflectMask = -1;
1338                 p->tex_Texture_ReflectCube = -1;
1339                 p->tex_Texture_BounceGrid = -1;
1340                 // bind the texture samplers in use
1341                 sampler = 0;
1342                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1343                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1344                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1345                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1346                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1347                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1348                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1349                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1353                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1354                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1355                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1356                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1357                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1358                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1359                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1360                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1361                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1362                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1363                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1364                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1365                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1368                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1370                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1371                 // get the uniform block indices so we can bind them
1372 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1373                 if (vid.support.arb_uniform_buffer_object)
1374                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1375                 else
1376 #endif
1377                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1378                 // clear the uniform block bindings
1379                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1380                 // bind the uniform blocks in use
1381                 ubibind = 0;
1382 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1383                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1384 #endif
1385                 // we're done compiling and setting up the shader, at least until it is used
1386                 CHECKGLERROR
1387                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1388         }
1389         else
1390                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1391
1392         // free the strings
1393         if (sourcestring)
1394                 Mem_Free(sourcestring);
1395 }
1396
1397 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1398 {
1399         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1400         if (r_glsl_permutation != perm)
1401         {
1402                 r_glsl_permutation = perm;
1403                 if (!r_glsl_permutation->program)
1404                 {
1405                         if (!r_glsl_permutation->compiled)
1406                         {
1407                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1408                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1409                         }
1410                         if (!r_glsl_permutation->program)
1411                         {
1412                                 // remove features until we find a valid permutation
1413                                 int i;
1414                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1415                                 {
1416                                         // reduce i more quickly whenever it would not remove any bits
1417                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1418                                         if (!(permutation & j))
1419                                                 continue;
1420                                         permutation -= j;
1421                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422                                         if (!r_glsl_permutation->compiled)
1423                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1424                                         if (r_glsl_permutation->program)
1425                                                 break;
1426                                 }
1427                                 if (i >= SHADERPERMUTATION_COUNT)
1428                                 {
1429                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1430                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1431                                         qglUseProgram(0);CHECKGLERROR
1432                                         return; // no bit left to clear, entire mode is broken
1433                                 }
1434                         }
1435                 }
1436                 CHECKGLERROR
1437                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1438         }
1439         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1440         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1441         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1442         CHECKGLERROR
1443 }
1444
1445 #ifdef SUPPORTD3D
1446
1447 #ifdef SUPPORTD3D
1448 #include <d3d9.h>
1449 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1450 extern D3DCAPS9 vid_d3d9caps;
1451 #endif
1452
1453 struct r_hlsl_permutation_s;
1454 typedef struct r_hlsl_permutation_s
1455 {
1456         /// hash lookup data
1457         struct r_hlsl_permutation_s *hashnext;
1458         unsigned int mode;
1459         dpuint64 permutation;
1460
1461         /// indicates if we have tried compiling this permutation already
1462         qboolean compiled;
1463         /// NULL if compilation failed
1464         IDirect3DVertexShader9 *vertexshader;
1465         IDirect3DPixelShader9 *pixelshader;
1466 }
1467 r_hlsl_permutation_t;
1468
1469 typedef enum D3DVSREGISTER_e
1470 {
1471         D3DVSREGISTER_TexMatrix = 0, // float4x4
1472         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1473         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1474         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1475         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1476         D3DVSREGISTER_ModelToLight = 20, // float4x4
1477         D3DVSREGISTER_EyePosition = 24,
1478         D3DVSREGISTER_FogPlane = 25,
1479         D3DVSREGISTER_LightDir = 26,
1480         D3DVSREGISTER_LightPosition = 27,
1481 }
1482 D3DVSREGISTER_t;
1483
1484 typedef enum D3DPSREGISTER_e
1485 {
1486         D3DPSREGISTER_Alpha = 0,
1487         D3DPSREGISTER_BloomBlur_Parameters = 1,
1488         D3DPSREGISTER_ClientTime = 2,
1489         D3DPSREGISTER_Color_Ambient = 3,
1490         D3DPSREGISTER_Color_Diffuse = 4,
1491         D3DPSREGISTER_Color_Specular = 5,
1492         D3DPSREGISTER_Color_Glow = 6,
1493         D3DPSREGISTER_Color_Pants = 7,
1494         D3DPSREGISTER_Color_Shirt = 8,
1495         D3DPSREGISTER_DeferredColor_Ambient = 9,
1496         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1497         D3DPSREGISTER_DeferredColor_Specular = 11,
1498         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1499         D3DPSREGISTER_DeferredMod_Specular = 13,
1500         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1501         D3DPSREGISTER_EyePosition = 15, // unused
1502         D3DPSREGISTER_FogColor = 16,
1503         D3DPSREGISTER_FogHeightFade = 17,
1504         D3DPSREGISTER_FogPlane = 18,
1505         D3DPSREGISTER_FogPlaneViewDist = 19,
1506         D3DPSREGISTER_FogRangeRecip = 20,
1507         D3DPSREGISTER_LightColor = 21,
1508         D3DPSREGISTER_LightDir = 22, // unused
1509         D3DPSREGISTER_LightPosition = 23,
1510         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1511         D3DPSREGISTER_PixelSize = 25,
1512         D3DPSREGISTER_ReflectColor = 26,
1513         D3DPSREGISTER_ReflectFactor = 27,
1514         D3DPSREGISTER_ReflectOffset = 28,
1515         D3DPSREGISTER_RefractColor = 29,
1516         D3DPSREGISTER_Saturation = 30,
1517         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1518         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1519         D3DPSREGISTER_ScreenToDepth = 33,
1520         D3DPSREGISTER_ShadowMap_Parameters = 34,
1521         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1522         D3DPSREGISTER_SpecularPower = 36,
1523         D3DPSREGISTER_UserVec1 = 37,
1524         D3DPSREGISTER_UserVec2 = 38,
1525         D3DPSREGISTER_UserVec3 = 39,
1526         D3DPSREGISTER_UserVec4 = 40,
1527         D3DPSREGISTER_ViewTintColor = 41,
1528         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1529         D3DPSREGISTER_BloomColorSubtract = 43,
1530         D3DPSREGISTER_ViewToLight = 44, // float4x4
1531         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1532         D3DPSREGISTER_NormalmapScrollBlend = 52,
1533         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1534         D3DPSREGISTER_OffsetMapping_Bias = 54,
1535         // next at 54
1536 }
1537 D3DPSREGISTER_t;
1538
1539 /// information about each possible shader permutation
1540 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1541 /// currently selected permutation
1542 r_hlsl_permutation_t *r_hlsl_permutation;
1543 /// storage for permutations linked in the hash table
1544 memexpandablearray_t r_hlsl_permutationarray;
1545
1546 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1547 {
1548         //unsigned int hashdepth = 0;
1549         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1550         r_hlsl_permutation_t *p;
1551         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1552         {
1553                 if (p->mode == mode && p->permutation == permutation)
1554                 {
1555                         //if (hashdepth > 10)
1556                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1557                         return p;
1558                 }
1559                 //hashdepth++;
1560         }
1561         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1562         p->mode = mode;
1563         p->permutation = permutation;
1564         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1565         r_hlsl_permutationhash[mode][hashindex] = p;
1566         //if (hashdepth > 10)
1567         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1568         return p;
1569 }
1570
1571 #include <d3dx9.h>
1572 //#include <d3dx9shader.h>
1573 //#include <d3dx9mesh.h>
1574
1575 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1576 {
1577         DWORD *vsbin = NULL;
1578         DWORD *psbin = NULL;
1579         fs_offset_t vsbinsize;
1580         fs_offset_t psbinsize;
1581 //      IDirect3DVertexShader9 *vs = NULL;
1582 //      IDirect3DPixelShader9 *ps = NULL;
1583         ID3DXBuffer *vslog = NULL;
1584         ID3DXBuffer *vsbuffer = NULL;
1585         ID3DXConstantTable *vsconstanttable = NULL;
1586         ID3DXBuffer *pslog = NULL;
1587         ID3DXBuffer *psbuffer = NULL;
1588         ID3DXConstantTable *psconstanttable = NULL;
1589         int vsresult = 0;
1590         int psresult = 0;
1591         char temp[MAX_INPUTLINE];
1592         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1593         char vabuf[1024];
1594         qboolean debugshader = gl_paranoid.integer != 0;
1595         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (!debugshader)
1598         {
1599                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1600                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1601         }
1602         if ((!vsbin && vertstring) || (!psbin && fragstring))
1603         {
1604                 const char* dllnames_d3dx9 [] =
1605                 {
1606                         "d3dx9_43.dll",
1607                         "d3dx9_42.dll",
1608                         "d3dx9_41.dll",
1609                         "d3dx9_40.dll",
1610                         "d3dx9_39.dll",
1611                         "d3dx9_38.dll",
1612                         "d3dx9_37.dll",
1613                         "d3dx9_36.dll",
1614                         "d3dx9_35.dll",
1615                         "d3dx9_34.dll",
1616                         "d3dx9_33.dll",
1617                         "d3dx9_32.dll",
1618                         "d3dx9_31.dll",
1619                         "d3dx9_30.dll",
1620                         "d3dx9_29.dll",
1621                         "d3dx9_28.dll",
1622                         "d3dx9_27.dll",
1623                         "d3dx9_26.dll",
1624                         "d3dx9_25.dll",
1625                         "d3dx9_24.dll",
1626                         NULL
1627                 };
1628                 dllhandle_t d3dx9_dll = NULL;
1629                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1630                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1631                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1632                 dllfunction_t d3dx9_dllfuncs[] =
1633                 {
1634                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1635                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1636                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1637                         {NULL, NULL}
1638                 };
1639                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1640 #ifndef ID3DXBuffer_GetBufferPointer
1641 #if !defined(__cplusplus) || defined(CINTERFACE)
1642 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1643 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1644 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1645 #else
1646 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1647 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1648 #define ID3DXBuffer_Release(p)            (p)->Release()
1649 #endif
1650 #endif
1651                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1652                 {
1653                         DWORD shaderflags = 0;
1654                         if (debugshader)
1655                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1656                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1657                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1658                         if (vertstring && vertstring[0])
1659                         {
1660                                 if (debugshader)
1661                                 {
1662                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1663                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1664                                 }
1665                                 else
1666                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1667                                 if (vsbuffer)
1668                                 {
1669                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1670                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1671                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1672                                         ID3DXBuffer_Release(vsbuffer);
1673                                 }
1674                                 if (vslog)
1675                                 {
1676                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1677                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1678                                         ID3DXBuffer_Release(vslog);
1679                                 }
1680                         }
1681                         if (fragstring && fragstring[0])
1682                         {
1683                                 if (debugshader)
1684                                 {
1685                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1686                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1687                                 }
1688                                 else
1689                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1690                                 if (psbuffer)
1691                                 {
1692                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1693                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1694                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1695                                         ID3DXBuffer_Release(psbuffer);
1696                                 }
1697                                 if (pslog)
1698                                 {
1699                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1700                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1701                                         ID3DXBuffer_Release(pslog);
1702                                 }
1703                         }
1704                         Sys_UnloadLibrary(&d3dx9_dll);
1705                 }
1706                 else
1707                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1708         }
1709         if (vsbin && psbin)
1710         {
1711                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1712                 if (FAILED(vsresult))
1713                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1714                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1715                 if (FAILED(psresult))
1716                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1717         }
1718         // free the shader data
1719         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1720         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1721 }
1722
1723 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1724 {
1725         int i;
1726         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1727         int vertstring_length = 0;
1728         int geomstring_length = 0;
1729         int fragstring_length = 0;
1730         char *t;
1731         char *sourcestring;
1732         char *vertstring, *geomstring, *fragstring;
1733         char permutationname[256];
1734         char cachename[256];
1735         int vertstrings_count = 0;
1736         int geomstrings_count = 0;
1737         int fragstrings_count = 0;
1738         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741
1742         if (p->compiled)
1743                 return;
1744         p->compiled = true;
1745         p->vertexshader = NULL;
1746         p->pixelshader = NULL;
1747
1748         permutationname[0] = 0;
1749         cachename[0] = 0;
1750         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1751
1752         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1753         strlcat(cachename, "hlsl/", sizeof(cachename));
1754
1755         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1756         vertstrings_count = 0;
1757         geomstrings_count = 0;
1758         fragstrings_count = 0;
1759         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1760         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1761         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1762
1763         // the first pretext is which type of shader to compile as
1764         // (later these will all be bound together as a program object)
1765         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1766         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1767         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1768
1769         // the second pretext is the mode (for example a light source)
1770         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1771         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1772         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1773         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1774         strlcat(cachename, modeinfo->name, sizeof(cachename));
1775
1776         // now add all the permutation pretexts
1777         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778         {
1779                 if (permutation & (1ll<<i))
1780                 {
1781                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1782                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1785                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1786                 }
1787                 else
1788                 {
1789                         // keep line numbers correct
1790                         vertstrings_list[vertstrings_count++] = "\n";
1791                         geomstrings_list[geomstrings_count++] = "\n";
1792                         fragstrings_list[fragstrings_count++] = "\n";
1793                 }
1794         }
1795
1796         // add static parms
1797         R_CompileShader_AddStaticParms(mode, permutation);
1798         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1799         vertstrings_count += shaderstaticparms_count;
1800         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1801         geomstrings_count += shaderstaticparms_count;
1802         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1803         fragstrings_count += shaderstaticparms_count;
1804
1805         // replace spaces in the cachename with _ characters
1806         for (i = 0;cachename[i];i++)
1807                 if (cachename[i] == ' ')
1808                         cachename[i] = '_';
1809
1810         // now append the shader text itself
1811         vertstrings_list[vertstrings_count++] = sourcestring;
1812         geomstrings_list[geomstrings_count++] = sourcestring;
1813         fragstrings_list[fragstrings_count++] = sourcestring;
1814
1815         vertstring_length = 0;
1816         for (i = 0;i < vertstrings_count;i++)
1817                 vertstring_length += (int)strlen(vertstrings_list[i]);
1818         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1819         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1820                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1821
1822         geomstring_length = 0;
1823         for (i = 0;i < geomstrings_count;i++)
1824                 geomstring_length += (int)strlen(geomstrings_list[i]);
1825         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1826         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1827                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1828
1829         fragstring_length = 0;
1830         for (i = 0;i < fragstrings_count;i++)
1831                 fragstring_length += (int)strlen(fragstrings_list[i]);
1832         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1833         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1834                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1835
1836         // try to load the cached shader, or generate one
1837         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1838
1839         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1840                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1841         else
1842                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1843
1844         // free the strings
1845         if (vertstring)
1846                 Mem_Free(vertstring);
1847         if (geomstring)
1848                 Mem_Free(geomstring);
1849         if (fragstring)
1850                 Mem_Free(fragstring);
1851         if (sourcestring)
1852                 Mem_Free(sourcestring);
1853 }
1854
1855 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1858 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1859 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1860 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1861
1862 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1863 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1864 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1865 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1866 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1867 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1868
1869 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1870 {
1871         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1872         if (r_hlsl_permutation != perm)
1873         {
1874                 r_hlsl_permutation = perm;
1875                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876                 {
1877                         if (!r_hlsl_permutation->compiled)
1878                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1879                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1880                         {
1881                                 // remove features until we find a valid permutation
1882                                 int i;
1883                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                                 {
1885                                         // reduce i more quickly whenever it would not remove any bits
1886                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1887                                         if (!(permutation & j))
1888                                                 continue;
1889                                         permutation -= j;
1890                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891                                         if (!r_hlsl_permutation->compiled)
1892                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1893                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1894                                                 break;
1895                                 }
1896                                 if (i >= SHADERPERMUTATION_COUNT)
1897                                 {
1898                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1899                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1900                                         return; // no bit left to clear, entire mode is broken
1901                                 }
1902                         }
1903                 }
1904                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1905                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1906         }
1907         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1909         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1910 }
1911 #endif
1912
1913 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1914 {
1915         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1916         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1918         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1919 }
1920
1921 void R_GLSL_Restart_f(void)
1922 {
1923         unsigned int i, limit;
1924         switch(vid.renderpath)
1925         {
1926         case RENDERPATH_D3D9:
1927 #ifdef SUPPORTD3D
1928                 {
1929                         r_hlsl_permutation_t *p;
1930                         r_hlsl_permutation = NULL;
1931                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1932                         for (i = 0;i < limit;i++)
1933                         {
1934                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1935                                 {
1936                                         if (p->vertexshader)
1937                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1938                                         if (p->pixelshader)
1939                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1940                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1941                                 }
1942                         }
1943                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1944                 }
1945 #endif
1946                 break;
1947         case RENDERPATH_D3D10:
1948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949                 break;
1950         case RENDERPATH_D3D11:
1951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_GLES2:
1955                 {
1956                         r_glsl_permutation_t *p;
1957                         r_glsl_permutation = NULL;
1958                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1959                         for (i = 0;i < limit;i++)
1960                         {
1961                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1962                                 {
1963                                         GL_Backend_FreeProgram(p->program);
1964                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1965                                 }
1966                         }
1967                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1968                 }
1969                 break;
1970         case RENDERPATH_GL11:
1971         case RENDERPATH_GL13:
1972         case RENDERPATH_GLES1:
1973                 break;
1974         case RENDERPATH_SOFT:
1975                 break;
1976         }
1977 }
1978
1979 static void R_GLSL_DumpShader_f(void)
1980 {
1981         int i, language, mode, dupe;
1982         char *text;
1983         shadermodeinfo_t *modeinfo;
1984         qfile_t *file;
1985
1986         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1987         {
1988                 modeinfo = shadermodeinfo[language];
1989                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1990                 {
1991                         // don't dump the same file multiple times (most or all shaders come from the same file)
1992                         for (dupe = mode - 1;dupe >= 0;dupe--)
1993                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1994                                         break;
1995                         if (dupe >= 0)
1996                                 continue;
1997                         text = modeinfo[mode].builtinstring;
1998                         if (!text)
1999                                 continue;
2000                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2001                         if (file)
2002                         {
2003                                 FS_Print(file, "/* The engine may define the following macros:\n");
2004                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2005                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2006                                         FS_Print(file, modeinfo[i].pretext);
2007                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2008                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2009                                 FS_Print(file, "*/\n");
2010                                 FS_Print(file, text);
2011                                 FS_Close(file);
2012                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2013                         }
2014                         else
2015                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2016                 }
2017         }
2018 }
2019
2020 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2021 {
2022         dpuint64 permutation = 0;
2023         if (r_trippy.integer && !notrippy)
2024                 permutation |= SHADERPERMUTATION_TRIPPY;
2025         permutation |= SHADERPERMUTATION_VIEWTINT;
2026         if (first)
2027                 permutation |= SHADERPERMUTATION_DIFFUSE;
2028         if (second)
2029                 permutation |= SHADERPERMUTATION_SPECULAR;
2030         if (texturemode == GL_MODULATE)
2031                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2032         else if (texturemode == GL_ADD)
2033                 permutation |= SHADERPERMUTATION_GLOW;
2034         else if (texturemode == GL_DECAL)
2035                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2036         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2037                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2038         if (suppresstexalpha)
2039                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2040         if (!second)
2041                 texturemode = GL_MODULATE;
2042         if (vid.allowalphatocoverage)
2043                 GL_AlphaToCoverage(false);
2044         switch (vid.renderpath)
2045         {
2046         case RENDERPATH_D3D9:
2047 #ifdef SUPPORTD3D
2048                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2049                 R_Mesh_TexBind(GL20TU_FIRST , first );
2050                 R_Mesh_TexBind(GL20TU_SECOND, second);
2051                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2052                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2053 #endif
2054                 break;
2055         case RENDERPATH_D3D10:
2056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057                 break;
2058         case RENDERPATH_D3D11:
2059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060                 break;
2061         case RENDERPATH_GL20:
2062         case RENDERPATH_GLES2:
2063                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2064                 if (r_glsl_permutation->tex_Texture_First >= 0)
2065                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2066                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2067                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2068                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2069                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2070                 break;
2071         case RENDERPATH_GL13:
2072         case RENDERPATH_GLES1:
2073                 R_Mesh_TexBind(0, first );
2074                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2075                 R_Mesh_TexMatrix(0, NULL);
2076                 R_Mesh_TexBind(1, second);
2077                 if (second)
2078                 {
2079                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2080                         R_Mesh_TexMatrix(1, NULL);
2081                 }
2082                 break;
2083         case RENDERPATH_GL11:
2084                 R_Mesh_TexBind(0, first );
2085                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2086                 R_Mesh_TexMatrix(0, NULL);
2087                 break;
2088         case RENDERPATH_SOFT:
2089                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2090                 R_Mesh_TexBind(GL20TU_FIRST , first );
2091                 R_Mesh_TexBind(GL20TU_SECOND, second);
2092                 break;
2093         }
2094 }
2095
2096 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2097 {
2098         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2099 }
2100
2101 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2102 {
2103         dpuint64 permutation = 0;
2104         if (r_trippy.integer && !notrippy)
2105                 permutation |= SHADERPERMUTATION_TRIPPY;
2106         if (depthrgb)
2107                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2108         if (skeletal)
2109                 permutation |= SHADERPERMUTATION_SKELETAL;
2110
2111         if (vid.allowalphatocoverage)
2112                 GL_AlphaToCoverage(false);
2113         switch (vid.renderpath)
2114         {
2115         case RENDERPATH_D3D9:
2116 #ifdef SUPPORTD3D
2117                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2118 #endif
2119                 break;
2120         case RENDERPATH_D3D10:
2121                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2122                 break;
2123         case RENDERPATH_D3D11:
2124                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2125                 break;
2126         case RENDERPATH_GL20:
2127         case RENDERPATH_GLES2:
2128                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2130                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2131 #endif
2132                 break;
2133         case RENDERPATH_GL13:
2134         case RENDERPATH_GLES1:
2135                 R_Mesh_TexBind(0, 0);
2136                 R_Mesh_TexBind(1, 0);
2137                 break;
2138         case RENDERPATH_GL11:
2139                 R_Mesh_TexBind(0, 0);
2140                 break;
2141         case RENDERPATH_SOFT:
2142                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2143                 break;
2144         }
2145 }
2146
2147 extern qboolean r_shadow_usingdeferredprepass;
2148 extern rtexture_t *r_shadow_attenuationgradienttexture;
2149 extern rtexture_t *r_shadow_attenuation2dtexture;
2150 extern rtexture_t *r_shadow_attenuation3dtexture;
2151 extern qboolean r_shadow_usingshadowmap2d;
2152 extern qboolean r_shadow_usingshadowmaportho;
2153 extern float r_shadow_modelshadowmap_texturescale[4];
2154 extern float r_shadow_modelshadowmap_parameters[4];
2155 extern float r_shadow_lightshadowmap_texturescale[4];
2156 extern float r_shadow_lightshadowmap_parameters[4];
2157 extern qboolean r_shadow_shadowmapvsdct;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2160 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2161 extern matrix4x4_t r_shadow_shadowmapmatrix;
2162 extern int r_shadow_prepass_width;
2163 extern int r_shadow_prepass_height;
2164 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2165 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2166 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2167 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2168
2169 #define BLENDFUNC_ALLOWS_COLORMOD      1
2170 #define BLENDFUNC_ALLOWS_FOG           2
2171 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2172 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2173 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2174 static int R_BlendFuncFlags(int src, int dst)
2175 {
2176         int r = 0;
2177
2178         // a blendfunc allows colormod if:
2179         // a) it can never keep the destination pixel invariant, or
2180         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2181         // this is to prevent unintended side effects from colormod
2182
2183         // a blendfunc allows fog if:
2184         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2185         // this is to prevent unintended side effects from fog
2186
2187         // these checks are the output of fogeval.pl
2188
2189         r |= BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2198         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2199         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2202         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2203         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2209         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2211
2212         return r;
2213 }
2214
2215 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2216 {
2217         // select a permutation of the lighting shader appropriate to this
2218         // combination of texture, entity, light source, and fogging, only use the
2219         // minimum features necessary to avoid wasting rendering time in the
2220         // fragment shader on features that are not being used
2221         dpuint64 permutation = 0;
2222         unsigned int mode = 0;
2223         int blendfuncflags;
2224         texture_t *t = rsurface.texture;
2225         float m16f[16];
2226         matrix4x4_t tempmatrix;
2227         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2228         if (r_trippy.integer && !notrippy)
2229                 permutation |= SHADERPERMUTATION_TRIPPY;
2230         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2231                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2232         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2233                 permutation |= SHADERPERMUTATION_OCCLUDE;
2234         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2235                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2236         if (rsurfacepass == RSURFPASS_BACKGROUND)
2237         {
2238                 // distorted background
2239                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2240                 {
2241                         mode = SHADERMODE_WATER;
2242                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2243                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2244                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2245                         {
2246                                 // this is the right thing to do for wateralpha
2247                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2248                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2249                         }
2250                         else
2251                         {
2252                                 // this is the right thing to do for entity alpha
2253                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                         }
2256                 }
2257                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2258                 {
2259                         mode = SHADERMODE_REFRACTION;
2260                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2261                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2262                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264                 }
2265                 else
2266                 {
2267                         mode = SHADERMODE_GENERIC;
2268                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2269                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2270                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271                 }
2272                 if (vid.allowalphatocoverage)
2273                         GL_AlphaToCoverage(false);
2274         }
2275         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2276         {
2277                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2278                 {
2279                         switch(t->offsetmapping)
2280                         {
2281                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2282                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_OFF: break;
2285                         }
2286                 }
2287                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2288                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2289                 // normalmap (deferred prepass), may use alpha test on diffuse
2290                 mode = SHADERMODE_DEFERREDGEOMETRY;
2291                 GL_BlendFunc(GL_ONE, GL_ZERO);
2292                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2293                 if (vid.allowalphatocoverage)
2294                         GL_AlphaToCoverage(false);
2295         }
2296         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2297         {
2298                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2299                 {
2300                         switch(t->offsetmapping)
2301                         {
2302                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2303                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305                         case OFFSETMAPPING_OFF: break;
2306                         }
2307                 }
2308                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2311                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2312                 // light source
2313                 mode = SHADERMODE_LIGHTSOURCE;
2314                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2315                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2316                 if (VectorLength2(rtlightdiffuse) > 0)
2317                         permutation |= SHADERPERMUTATION_DIFFUSE;
2318                 if (VectorLength2(rtlightspecular) > 0)
2319                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2320                 if (r_refdef.fogenabled)
2321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322                 if (t->colormapping)
2323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2324                 if (r_shadow_usingshadowmap2d)
2325                 {
2326                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2327                         if(r_shadow_shadowmapvsdct)
2328                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2329
2330                         if (r_shadow_shadowmap2ddepthbuffer)
2331                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2332                 }
2333                 if (t->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2336                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2337                 if (vid.allowalphatocoverage)
2338                         GL_AlphaToCoverage(false);
2339         }
2340         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341         {
2342                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2343                 {
2344                         switch(t->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2355                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2356                 // directional model lighting
2357                 mode = SHADERMODE_LIGHTDIRECTION;
2358                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2359                         permutation |= SHADERPERMUTATION_GLOW;
2360                 if (VectorLength2(t->render_modellight_diffuse))
2361                         permutation |= SHADERPERMUTATION_DIFFUSE;
2362                 if (VectorLength2(t->render_modellight_specular) > 0)
2363                         permutation |= SHADERPERMUTATION_SPECULAR;
2364                 if (r_refdef.fogenabled)
2365                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2366                 if (t->colormapping)
2367                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2368                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369                 {
2370                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2371                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372
2373                         if (r_shadow_shadowmap2ddepthbuffer)
2374                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2375                 }
2376                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2377                         permutation |= SHADERPERMUTATION_REFLECTION;
2378                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2379                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2380                 if (t->reflectmasktexture)
2381                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2382                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2383                 {
2384                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2385                         if (r_shadow_bouncegrid_state.directional)
2386                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2387                 }
2388                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2390                 // when using alphatocoverage, we don't need alphakill
2391                 if (vid.allowalphatocoverage)
2392                 {
2393                         if (r_transparent_alphatocoverage.integer)
2394                         {
2395                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2396                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2397                         }
2398                         else
2399                                 GL_AlphaToCoverage(false);
2400                 }
2401         }
2402         else
2403         {
2404                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2405                 {
2406                         switch(t->offsetmapping)
2407                         {
2408                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2409                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_OFF: break;
2412                         }
2413                 }
2414                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2415                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2416                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2417                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2418                 // lightmapped wall
2419                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420                         permutation |= SHADERPERMUTATION_GLOW;
2421                 if (r_refdef.fogenabled)
2422                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2423                 if (t->colormapping)
2424                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2425                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426                 {
2427                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2428                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429
2430                         if (r_shadow_shadowmap2ddepthbuffer)
2431                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2432                 }
2433                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (t->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (VectorLength2(t->render_lightmap_specular) > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (VectorLength2(t->render_lightmap_specular) > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         if (rsurface.uselightmaptexture)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (VectorLength2(t->render_lightmap_specular) > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegrid_state.directional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2500                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2501         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2502                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2503         switch(vid.renderpath)
2504         {
2505         case RENDERPATH_D3D9:
2506 #ifdef SUPPORTD3D
2507                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2508                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2509                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2510                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2511                 if (mode == SHADERMODE_LIGHTSOURCE)
2512                 {
2513                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2514                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2515                 }
2516                 else
2517                 {
2518                         if (mode == SHADERMODE_LIGHTDIRECTION)
2519                         {
2520                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2521                         }
2522                 }
2523                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2526                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2527                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2536
2537                         // additive passes are only darkened by fog, not tinted
2538                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2539                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2540                 }
2541                 else
2542                 {
2543                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2556                         }
2557                         else
2558                         {
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2562                         }
2563                         // additive passes are only darkened by fog, not tinted
2564                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         else
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2568                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2573                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2576                         if (mode == SHADERMODE_WATER)
2577                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2578                 }
2579                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2580                 {
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2583                 }
2584                 else
2585                 {
2586                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2588                 }
2589                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2590                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2591                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2592                 if (t->pantstexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2596                 if (t->shirttexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2603                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2605                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2606                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2608                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2609                         );
2610                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2611                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2612                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2613                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2614
2615                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2616                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2617                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2618                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2627                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2628                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2629                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2630                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2631                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2632                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2633                 {
2634                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2635                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2636                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638                 else
2639                 {
2640                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2643                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2645                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2646                 {
2647                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2648                         if (rsurface.rtlight)
2649                         {
2650                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2651                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2652                         }
2653                 }
2654 #endif
2655                 break;
2656         case RENDERPATH_D3D10:
2657                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658                 break;
2659         case RENDERPATH_D3D11:
2660                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2661                 break;
2662         case RENDERPATH_GL20:
2663         case RENDERPATH_GLES2:
2664                 if (!vid.useinterleavedarrays)
2665                 {
2666                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2667                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2668                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2675                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2676                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2677                 }
2678                 else
2679                 {
2680                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2681                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2682                 }
2683                 // this has to be after RSurf_PrepareVerticesForBatch
2684                 if (rsurface.batchskeletaltransform3x4buffer)
2685                         permutation |= SHADERPERMUTATION_SKELETAL;
2686                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2687 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2688                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2689 #endif
2690                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2691                 if (mode == SHADERMODE_LIGHTSOURCE)
2692                 {
2693                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2694                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2695                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2696                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2697                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2698                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2699         
2700                         // additive passes are only darkened by fog, not tinted
2701                         if (r_glsl_permutation->loc_FogColor >= 0)
2702                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2703                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2704                 }
2705                 else
2706                 {
2707                         if (mode == SHADERMODE_FLATCOLOR)
2708                         {
2709                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2710                         }
2711                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2712                         {
2713                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2714                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2715                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2716                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2717                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2718                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2719                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2720                         }
2721                         else
2722                         {
2723                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2724                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2725                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2726                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2728                         }
2729                         // additive passes are only darkened by fog, not tinted
2730                         if (r_glsl_permutation->loc_FogColor >= 0)
2731                         {
2732                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2733                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2734                                 else
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2736                         }
2737                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2738                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2739                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2740                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2741                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2742                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2743                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2744                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2745                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2746                 }
2747                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2750                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2751                 {
2752                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2753                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2754                 }
2755                 else
2756                 {
2757                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2758                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2759                 }
2760
2761                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2762                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2763                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2764                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2765                 {
2766                         if (t->pantstexture)
2767                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2768                         else
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2770                 }
2771                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2772                 {
2773                         if (t->shirttexture)
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2775                         else
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2777                 }
2778                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2779                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2780                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2781                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2782                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2783                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2784                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2786                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2787                         );
2788                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2789                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2790                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2791                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2792                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2793                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2794
2795                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2796                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2797                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2798                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2799                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2800                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2801                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2802                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2806                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2807                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2808                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2809                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2810                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2811                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2812                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2813                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2814                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2815                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2816                 {
2817                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2818                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2819                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2820                 }
2821                 else
2822                 {
2823                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2824                 }
2825                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2826                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2827                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2828                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2829                 {
2830                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2831                         if (rsurface.rtlight)
2832                         {
2833                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2834                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2835                         }
2836                 }
2837                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2838                 CHECKGLERROR
2839                 break;
2840         case RENDERPATH_GL11:
2841         case RENDERPATH_GL13:
2842         case RENDERPATH_GLES1:
2843                 break;
2844         case RENDERPATH_SOFT:
2845                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2846                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2847                 R_SetupShader_SetPermutationSoft(mode, permutation);
2848                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2849                 if (mode == SHADERMODE_LIGHTSOURCE)
2850                 {
2851                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2857         
2858                         // additive passes are only darkened by fog, not tinted
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2860                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2861                 }
2862                 else
2863                 {
2864                         if (mode == SHADERMODE_FLATCOLOR)
2865                         {
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2867                         }
2868                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2875                         }
2876                         else
2877                         {
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2881                         }
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2884                         // additive passes are only darkened by fog, not tinted
2885                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2887                         else
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2889                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2896                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2897                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2898                 }
2899                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2900                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2901                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2902                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2903                 {
2904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2906                 }
2907                 else
2908                 {
2909                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2910                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2911                 }
2912
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2915                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2916                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2917                 {
2918                         if (t->pantstexture)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2922                 }
2923                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2924                 {
2925                         if (t->shirttexture)
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2927                         else
2928                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2929                 }
2930                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2934                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2935                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2936                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2939                         );
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2943                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2944
2945                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2946                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2947                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2948                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2957                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2958                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2959                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2960                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2961                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2962                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2963                 {
2964                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2965                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2966                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968                 else
2969                 {
2970                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971                 }
2972 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2974                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2975                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2976                 {
2977                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2978                         if (rsurface.rtlight)
2979                         {
2980                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2981                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2982                         }
2983                 }
2984                 break;
2985         }
2986 }
2987
2988 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2989 {
2990         // select a permutation of the lighting shader appropriate to this
2991         // combination of texture, entity, light source, and fogging, only use the
2992         // minimum features necessary to avoid wasting rendering time in the
2993         // fragment shader on features that are not being used
2994         dpuint64 permutation = 0;
2995         unsigned int mode = 0;
2996         const float *lightcolorbase = rtlight->currentcolor;
2997         float ambientscale = rtlight->ambientscale;
2998         float diffusescale = rtlight->diffusescale;
2999         float specularscale = rtlight->specularscale;
3000         // this is the location of the light in view space
3001         vec3_t viewlightorigin;
3002         // this transforms from view space (camera) to light space (cubemap)
3003         matrix4x4_t viewtolight;
3004         matrix4x4_t lighttoview;
3005         float viewtolight16f[16];
3006         // light source
3007         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3008         if (rtlight->currentcubemap != r_texture_whitecube)
3009                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3010         if (diffusescale > 0)
3011                 permutation |= SHADERPERMUTATION_DIFFUSE;
3012         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3013                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3014         if (r_shadow_usingshadowmap2d)
3015         {
3016                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3017                 if (r_shadow_shadowmapvsdct)
3018                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3019
3020                 if (r_shadow_shadowmap2ddepthbuffer)
3021                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3022         }
3023         if (vid.allowalphatocoverage)
3024                 GL_AlphaToCoverage(false);
3025         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3026         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3027         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3028         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3029         switch(vid.renderpath)
3030         {
3031         case RENDERPATH_D3D9:
3032 #ifdef SUPPORTD3D
3033                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3040                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3041                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3044
3045                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3046                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3047                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3048                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3049                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3050 #endif
3051                 break;
3052         case RENDERPATH_D3D10:
3053                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054                 break;
3055         case RENDERPATH_D3D11:
3056                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057                 break;
3058         case RENDERPATH_GL20:
3059         case RENDERPATH_GLES2:
3060                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3063                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3065                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3066                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3067                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3068                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3069                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3070                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3071
3072                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3073                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3074                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3075                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3076                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3077                 break;
3078         case RENDERPATH_GL11:
3079         case RENDERPATH_GL13:
3080         case RENDERPATH_GLES1:
3081                 break;
3082         case RENDERPATH_SOFT:
3083                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3085                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3089                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3090                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3091                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3092                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3093                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3094
3095                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3096                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3097                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3098                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3099                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3100                 break;
3101         }
3102 }
3103
3104 #define SKINFRAME_HASH 1024
3105
3106 typedef struct
3107 {
3108         unsigned int loadsequence; // incremented each level change
3109         memexpandablearray_t array;
3110         skinframe_t *hash[SKINFRAME_HASH];
3111 }
3112 r_skinframe_t;
3113 r_skinframe_t r_skinframe;
3114
3115 void R_SkinFrame_PrepareForPurge(void)
3116 {
3117         r_skinframe.loadsequence++;
3118         // wrap it without hitting zero
3119         if (r_skinframe.loadsequence >= 200)
3120                 r_skinframe.loadsequence = 1;
3121 }
3122
3123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3124 {
3125         if (!skinframe)
3126                 return;
3127         // mark the skinframe as used for the purging code
3128         skinframe->loadsequence = r_skinframe.loadsequence;
3129 }
3130
3131 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3132 {
3133         if (s->merged == s->base)
3134                 s->merged = NULL;
3135         R_PurgeTexture(s->stain); s->stain = NULL;
3136         R_PurgeTexture(s->merged); s->merged = NULL;
3137         R_PurgeTexture(s->base); s->base = NULL;
3138         R_PurgeTexture(s->pants); s->pants = NULL;
3139         R_PurgeTexture(s->shirt); s->shirt = NULL;
3140         R_PurgeTexture(s->nmap); s->nmap = NULL;
3141         R_PurgeTexture(s->gloss); s->gloss = NULL;
3142         R_PurgeTexture(s->glow); s->glow = NULL;
3143         R_PurgeTexture(s->fog); s->fog = NULL;
3144         R_PurgeTexture(s->reflect); s->reflect = NULL;
3145         s->loadsequence = 0;
3146 }
3147
3148 void R_SkinFrame_Purge(void)
3149 {
3150         int i;
3151         skinframe_t *s;
3152         for (i = 0;i < SKINFRAME_HASH;i++)
3153         {
3154                 for (s = r_skinframe.hash[i];s;s = s->next)
3155                 {
3156                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3157                                 R_SkinFrame_PurgeSkinFrame(s);
3158                 }
3159         }
3160 }
3161
3162 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3163         skinframe_t *item;
3164         char basename[MAX_QPATH];
3165
3166         Image_StripImageExtension(name, basename, sizeof(basename));
3167
3168         if( last == NULL ) {
3169                 int hashindex;
3170                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3171                 item = r_skinframe.hash[hashindex];
3172         } else {
3173                 item = last->next;
3174         }
3175
3176         // linearly search through the hash bucket
3177         for( ; item ; item = item->next ) {
3178                 if( !strcmp( item->basename, basename ) ) {
3179                         return item;
3180                 }
3181         }
3182         return NULL;
3183 }
3184
3185 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3186 {
3187         skinframe_t *item;
3188         int hashindex;
3189         char basename[MAX_QPATH];
3190
3191         Image_StripImageExtension(name, basename, sizeof(basename));
3192
3193         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3195                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3196                         break;
3197
3198         if (!item) {
3199                 rtexture_t *dyntexture;
3200                 // check whether its a dynamic texture
3201                 dyntexture = CL_GetDynTexture( basename );
3202                 if (!add && !dyntexture)
3203                         return NULL;
3204                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3205                 memset(item, 0, sizeof(*item));
3206                 strlcpy(item->basename, basename, sizeof(item->basename));
3207                 item->base = dyntexture; // either NULL or dyntexture handle
3208                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3209                 item->comparewidth = comparewidth;
3210                 item->compareheight = compareheight;
3211                 item->comparecrc = comparecrc;
3212                 item->next = r_skinframe.hash[hashindex];
3213                 r_skinframe.hash[hashindex] = item;
3214         }
3215         else if (textureflags & TEXF_FORCE_RELOAD)
3216         {
3217                 rtexture_t *dyntexture;
3218                 // check whether its a dynamic texture
3219                 dyntexture = CL_GetDynTexture( basename );
3220                 if (!add && !dyntexture)
3221                         return NULL;
3222                 R_SkinFrame_PurgeSkinFrame(item);
3223         }
3224         else if( item->base == NULL )
3225         {
3226                 rtexture_t *dyntexture;
3227                 // check whether its a dynamic texture
3228                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3229                 dyntexture = CL_GetDynTexture( basename );
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231         }
3232
3233         R_SkinFrame_MarkUsed(item);
3234         return item;
3235 }
3236
3237 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3238         { \
3239                 unsigned long long avgcolor[5], wsum; \
3240                 int pix, comp, w; \
3241                 avgcolor[0] = 0; \
3242                 avgcolor[1] = 0; \
3243                 avgcolor[2] = 0; \
3244                 avgcolor[3] = 0; \
3245                 avgcolor[4] = 0; \
3246                 wsum = 0; \
3247                 for(pix = 0; pix < cnt; ++pix) \
3248                 { \
3249                         w = 0; \
3250                         for(comp = 0; comp < 3; ++comp) \
3251                                 w += getpixel; \
3252                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3253                         { \
3254                                 ++wsum; \
3255                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                                 w = getpixel; \
3257                                 for(comp = 0; comp < 3; ++comp) \
3258                                         avgcolor[comp] += getpixel * w; \
3259                                 avgcolor[3] += w; \
3260                         } \
3261                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3262                         avgcolor[4] += getpixel; \
3263                 } \
3264                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3265                         avgcolor[3] = 1; \
3266                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3267                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3270         }
3271
3272 extern cvar_t gl_picmip;
3273 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3274 {
3275         int j;
3276         unsigned char *pixels;
3277         unsigned char *bumppixels;
3278         unsigned char *basepixels = NULL;
3279         int basepixels_width = 0;
3280         int basepixels_height = 0;
3281         skinframe_t *skinframe;
3282         rtexture_t *ddsbase = NULL;
3283         qboolean ddshasalpha = false;
3284         float ddsavgcolor[4];
3285         char basename[MAX_QPATH];
3286         int miplevel = R_PicmipForFlags(textureflags);
3287         int savemiplevel = miplevel;
3288         int mymiplevel;
3289         char vabuf[1024];
3290
3291         if (cls.state == ca_dedicated)
3292                 return NULL;
3293
3294         // return an existing skinframe if already loaded
3295         // if loading of the first image fails, don't make a new skinframe as it
3296         // would cause all future lookups of this to be missing
3297         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3298         if (skinframe && skinframe->base)
3299                 return skinframe;
3300
3301         Image_StripImageExtension(name, basename, sizeof(basename));
3302
3303         // check for DDS texture file first
3304         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3305         {
3306                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3307                 if (basepixels == NULL)
3308                         return NULL;
3309         }
3310
3311         // FIXME handle miplevel
3312
3313         if (developer_loading.integer)
3314                 Con_Printf("loading skin \"%s\"\n", name);
3315
3316         // we've got some pixels to store, so really allocate this new texture now
3317         if (!skinframe)
3318                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3319         textureflags &= ~TEXF_FORCE_RELOAD;
3320         skinframe->stain = NULL;
3321         skinframe->merged = NULL;
3322         skinframe->base = NULL;
3323         skinframe->pants = NULL;
3324         skinframe->shirt = NULL;
3325         skinframe->nmap = NULL;
3326         skinframe->gloss = NULL;
3327         skinframe->glow = NULL;
3328         skinframe->fog = NULL;
3329         skinframe->reflect = NULL;
3330         skinframe->hasalpha = false;
3331         // we could store the q2animname here too
3332
3333         if (ddsbase)
3334         {
3335                 skinframe->base = ddsbase;
3336                 skinframe->hasalpha = ddshasalpha;
3337                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3338                 if (r_loadfog && skinframe->hasalpha)
3339                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3340                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3341         }
3342         else
3343         {
3344                 basepixels_width = image_width;
3345                 basepixels_height = image_height;
3346                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3347                 if (textureflags & TEXF_ALPHA)
3348                 {
3349                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3350                         {
3351                                 if (basepixels[j] < 255)
3352                                 {
3353                                         skinframe->hasalpha = true;
3354                                         break;
3355                                 }
3356                         }
3357                         if (r_loadfog && skinframe->hasalpha)
3358                         {
3359                                 // has transparent pixels
3360                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3361                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3362                                 {
3363                                         pixels[j+0] = 255;
3364                                         pixels[j+1] = 255;
3365                                         pixels[j+2] = 255;
3366                                         pixels[j+3] = basepixels[j+3];
3367                                 }
3368                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3369                                 Mem_Free(pixels);
3370                         }
3371                 }
3372                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3373 #ifndef USE_GLES2
3374                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3375                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3376                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3377                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3378                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3379 #endif
3380         }
3381
3382         if (r_loaddds)
3383         {
3384                 mymiplevel = savemiplevel;
3385                 if (r_loadnormalmap)
3386                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3387                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3388                 if (r_loadgloss)
3389                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3390                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3391                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3392                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3393         }
3394
3395         // _norm is the name used by tenebrae and has been adopted as standard
3396         if (r_loadnormalmap && skinframe->nmap == NULL)
3397         {
3398                 mymiplevel = savemiplevel;
3399                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3402                         Mem_Free(pixels);
3403                         pixels = NULL;
3404                 }
3405                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3406                 {
3407                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3408                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3409                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3410                         Mem_Free(pixels);
3411                         Mem_Free(bumppixels);
3412                 }
3413                 else if (r_shadow_bumpscale_basetexture.value > 0)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3417                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3418                         Mem_Free(pixels);
3419                 }
3420 #ifndef USE_GLES2
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3422                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3423 #endif
3424         }
3425
3426         // _luma is supported only for tenebrae compatibility
3427         // _blend and .blend are supported only for Q3 & QL compatibility, this hack can be removed if better Q3 shader support is implemented
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.blend", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_blend", 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                 return; // don't bother
6230         case RENDERPATH_GLES2:
6231         case RENDERPATH_D3D9:
6232         case RENDERPATH_D3D10:
6233         case RENDERPATH_D3D11:
6234                 r_fb.usedepthtextures = false;
6235                 break;
6236         case RENDERPATH_SOFT:
6237                 r_fb.usedepthtextures = true;
6238                 break;
6239         }
6240
6241         if (r_viewscale_fpsscaling.integer)
6242         {
6243                 double actualframetime;
6244                 double targetframetime;
6245                 double adjust;
6246                 actualframetime = r_refdef.lastdrawscreentime;
6247                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6248                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6249                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6250                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6251                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6252                 viewscalefpsadjusted += adjust;
6253                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6254         }
6255         else
6256                 viewscalefpsadjusted = 1.0f;
6257
6258         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6259
6260         switch(vid.renderpath)
6261         {
6262         case RENDERPATH_GL20:
6263         case RENDERPATH_D3D9:
6264         case RENDERPATH_D3D10:
6265         case RENDERPATH_D3D11:
6266         case RENDERPATH_SOFT:
6267         case RENDERPATH_GLES2:
6268                 break;
6269         case RENDERPATH_GL11:
6270         case RENDERPATH_GL13:
6271         case RENDERPATH_GLES1:
6272                 return;
6273         }
6274
6275         // set bloomwidth and bloomheight to the bloom resolution that will be
6276         // used (often less than the screen resolution for faster rendering)
6277         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6278         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6279         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6280         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6281         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6282
6283         // calculate desired texture sizes
6284         if (vid.support.arb_texture_non_power_of_two)
6285         {
6286                 screentexturewidth = vid.width;
6287                 screentextureheight = vid.height;
6288                 bloomtexturewidth = r_fb.bloomwidth;
6289                 bloomtextureheight = r_fb.bloomheight;
6290         }
6291         else
6292         {
6293                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6294                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6295                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6296                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6297         }
6298
6299         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))
6300         {
6301                 Cvar_SetValueQuick(&r_bloom, 0);
6302                 Cvar_SetValueQuick(&r_motionblur, 0);
6303                 Cvar_SetValueQuick(&r_damageblur, 0);
6304         }
6305
6306         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6307          && !r_bloom.integer
6308          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6309          && !useviewfbo
6310          && r_viewscale.value == 1.0f
6311          && !r_viewscale_fpsscaling.integer)
6312                 screentexturewidth = screentextureheight = 0;
6313         if (!r_bloom.integer)
6314                 bloomtexturewidth = bloomtextureheight = 0;
6315
6316         // allocate textures as needed
6317         if (r_fb.screentexturewidth != screentexturewidth
6318          || r_fb.screentextureheight != screentextureheight
6319          || r_fb.bloomtexturewidth != bloomtexturewidth
6320          || r_fb.bloomtextureheight != bloomtextureheight
6321          || r_fb.textype != textype
6322          || useviewfbo != (r_fb.fbo != 0))
6323         {
6324                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6325                 {
6326                         if (r_fb.bloomtexture[i])
6327                                 R_FreeTexture(r_fb.bloomtexture[i]);
6328                         r_fb.bloomtexture[i] = NULL;
6329
6330                         if (r_fb.bloomfbo[i])
6331                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6332                         r_fb.bloomfbo[i] = 0;
6333                 }
6334
6335                 if (r_fb.fbo)
6336                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6337                 r_fb.fbo = 0;
6338
6339                 if (r_fb.colortexture)
6340                         R_FreeTexture(r_fb.colortexture);
6341                 r_fb.colortexture = NULL;
6342
6343                 if (r_fb.depthtexture)
6344                         R_FreeTexture(r_fb.depthtexture);
6345                 r_fb.depthtexture = NULL;
6346
6347                 if (r_fb.ghosttexture)
6348                         R_FreeTexture(r_fb.ghosttexture);
6349                 r_fb.ghosttexture = NULL;
6350
6351                 r_fb.screentexturewidth = screentexturewidth;
6352                 r_fb.screentextureheight = screentextureheight;
6353                 r_fb.bloomtexturewidth = bloomtexturewidth;
6354                 r_fb.bloomtextureheight = bloomtextureheight;
6355                 r_fb.textype = textype;
6356
6357                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6358                 {
6359                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6360                                 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);
6361                         r_fb.ghosttexture_valid = false;
6362                         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);
6363                         if (useviewfbo)
6364                         {
6365                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6366                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6367                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6368                         }
6369                 }
6370
6371                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6372                 {
6373                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6374                         {
6375                                 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);
6376                                 if (useviewfbo)
6377                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6378                         }
6379                 }
6380         }
6381
6382         // bloom texture is a different resolution
6383         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6384         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6385         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6386         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6387         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6388
6389         // set up a texcoord array for the full resolution screen image
6390         // (we have to keep this around to copy back during final render)
6391         r_fb.screentexcoord2f[0] = 0;
6392         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6393         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6394         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6395         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6396         r_fb.screentexcoord2f[5] = 0;
6397         r_fb.screentexcoord2f[6] = 0;
6398         r_fb.screentexcoord2f[7] = 0;
6399
6400         if(r_fb.fbo) 
6401         {
6402                 for (i = 1;i < 8;i += 2)
6403                 {
6404                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6405                 }
6406         }
6407
6408         // set up a texcoord array for the reduced resolution bloom image
6409         // (which will be additive blended over the screen image)
6410         r_fb.bloomtexcoord2f[0] = 0;
6411         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6412         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6413         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6414         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6415         r_fb.bloomtexcoord2f[5] = 0;
6416         r_fb.bloomtexcoord2f[6] = 0;
6417         r_fb.bloomtexcoord2f[7] = 0;
6418
6419         switch(vid.renderpath)
6420         {
6421         case RENDERPATH_GL11:
6422         case RENDERPATH_GL13:
6423         case RENDERPATH_GL20:
6424         case RENDERPATH_SOFT:
6425         case RENDERPATH_GLES1:
6426         case RENDERPATH_GLES2:
6427                 break;
6428         case RENDERPATH_D3D9:
6429         case RENDERPATH_D3D10:
6430         case RENDERPATH_D3D11:
6431                 for (i = 0;i < 4;i++)
6432                 {
6433                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6434                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6435                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6436                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6437                 }
6438                 break;
6439         }
6440
6441         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6442
6443         if (r_fb.fbo)
6444                 r_refdef.view.clear = true;
6445 }
6446
6447 static void R_Bloom_MakeTexture(void)
6448 {
6449         int x, range, dir;
6450         float xoffset, yoffset, r, brighten;
6451         rtexture_t *intex;
6452         float colorscale = r_bloom_colorscale.value;
6453
6454         r_refdef.stats[r_stat_bloom]++;
6455     
6456 #if 0
6457     // this copy is unnecessary since it happens in R_BlendView already
6458         if (!r_fb.fbo)
6459         {
6460                 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);
6461                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6462         }
6463 #endif
6464
6465         // scale down screen texture to the bloom texture size
6466         CHECKGLERROR
6467         r_fb.bloomindex = 0;
6468         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6469         R_SetViewport(&r_fb.bloomviewport);
6470         GL_CullFace(GL_NONE);
6471         GL_DepthTest(false);
6472         GL_BlendFunc(GL_ONE, GL_ZERO);
6473         GL_Color(colorscale, colorscale, colorscale, 1);
6474         // 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...
6475         switch(vid.renderpath)
6476         {
6477         case RENDERPATH_GL11:
6478         case RENDERPATH_GL13:
6479         case RENDERPATH_GL20:
6480         case RENDERPATH_GLES1:
6481         case RENDERPATH_GLES2:
6482         case RENDERPATH_SOFT:
6483                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6484                 break;
6485         case RENDERPATH_D3D9:
6486         case RENDERPATH_D3D10:
6487         case RENDERPATH_D3D11:
6488                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6489                 break;
6490         }
6491         // TODO: do boxfilter scale-down in shader?
6492         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6493         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6494         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6495
6496         // we now have a properly scaled bloom image
6497         if (!r_fb.bloomfbo[r_fb.bloomindex])
6498         {
6499                 // copy it into the bloom texture
6500                 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);
6501                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6502         }
6503
6504         // multiply bloom image by itself as many times as desired
6505         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6506         {
6507                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6508                 r_fb.bloomindex ^= 1;
6509                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6510                 x *= 2;
6511                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6512                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6513                 {
6514                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6515                         GL_Color(r,r,r,1); // apply fix factor
6516                 }
6517                 else
6518                 {
6519                         if(x <= 2)
6520                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6521                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6522                         GL_Color(1,1,1,1); // no fix factor supported here
6523                 }
6524                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6525                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6526                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6527                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6528
6529                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6530                 {
6531                         // copy the darkened image to a texture
6532                         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);
6533                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6534                 }
6535         }
6536
6537         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6538         brighten = r_bloom_brighten.value;
6539         brighten = sqrt(brighten);
6540         if(range >= 1)
6541                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6542
6543         for (dir = 0;dir < 2;dir++)
6544         {
6545                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6546                 r_fb.bloomindex ^= 1;
6547                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6548                 // blend on at multiple vertical offsets to achieve a vertical blur
6549                 // TODO: do offset blends using GLSL
6550                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6551                 GL_BlendFunc(GL_ONE, GL_ZERO);
6552                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6553                 for (x = -range;x <= range;x++)
6554                 {
6555                         if (!dir){xoffset = 0;yoffset = x;}
6556                         else {xoffset = x;yoffset = 0;}
6557                         xoffset /= (float)r_fb.bloomtexturewidth;
6558                         yoffset /= (float)r_fb.bloomtextureheight;
6559                         // compute a texcoord array with the specified x and y offset
6560                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6561                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6562                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6563                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6564                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6565                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6566                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6567                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6568                         // this r value looks like a 'dot' particle, fading sharply to
6569                         // black at the edges
6570                         // (probably not realistic but looks good enough)
6571                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6572                         //r = brighten/(range*2+1);
6573                         r = brighten / (range * 2 + 1);
6574                         if(range >= 1)
6575                                 r *= (1 - x*x/(float)(range*range));
6576                         GL_Color(r, r, r, 1);
6577                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6578                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6579                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6580                         GL_BlendFunc(GL_ONE, GL_ONE);
6581                 }
6582
6583                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6584                 {
6585                         // copy the vertically or horizontally blurred bloom view to a texture
6586                         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);
6587                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6588                 }
6589         }
6590 }
6591
6592 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6593 {
6594         dpuint64 permutation;
6595         float uservecs[4][4];
6596
6597         R_EntityMatrix(&identitymatrix);
6598
6599         switch (vid.renderpath)
6600         {
6601         case RENDERPATH_GL20:
6602         case RENDERPATH_D3D9:
6603         case RENDERPATH_D3D10:
6604         case RENDERPATH_D3D11:
6605         case RENDERPATH_SOFT:
6606         case RENDERPATH_GLES2:
6607                 permutation =
6608                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6609                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6610                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6611                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6612                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6613
6614                 if (r_fb.colortexture)
6615                 {
6616                         if (!r_fb.fbo)
6617                         {
6618                                 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);
6619                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6620                         }
6621
6622                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6623                         {
6624                                 // declare variables
6625                                 float blur_factor, blur_mouseaccel, blur_velocity;
6626                                 static float blur_average; 
6627                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6628
6629                                 // set a goal for the factoring
6630                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6631                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6632                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6633                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6634                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6635                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6636
6637                                 // from the goal, pick an averaged value between goal and last value
6638                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6639                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6640
6641                                 // enforce minimum amount of blur 
6642                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6643
6644                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6645
6646                                 // calculate values into a standard alpha
6647                                 cl.motionbluralpha = 1 - exp(-
6648                                                 (
6649                                                  (r_motionblur.value * blur_factor / 80)
6650                                                  +
6651                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6652                                                 )
6653                                                 /
6654                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6655                                           );
6656
6657                                 // randomization for the blur value to combat persistent ghosting
6658                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6659                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6660
6661                                 // apply the blur
6662                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6663                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6664                                 {
6665                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6666                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6667                                         switch(vid.renderpath)
6668                                         {
6669                                         case RENDERPATH_GL11:
6670                                         case RENDERPATH_GL13:
6671                                         case RENDERPATH_GL20:
6672                                         case RENDERPATH_GLES1:
6673                                         case RENDERPATH_GLES2:
6674                                         case RENDERPATH_SOFT:
6675                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6676                                                 break;
6677                                         case RENDERPATH_D3D9:
6678                                         case RENDERPATH_D3D10:
6679                                         case RENDERPATH_D3D11:
6680                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6681                                                 break;
6682                                         }
6683                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6684                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6685                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6686                                 }
6687
6688                                 // updates old view angles for next pass
6689                                 VectorCopy(cl.viewangles, blur_oldangles);
6690
6691                                 // copy view into the ghost texture
6692                                 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);
6693                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6694                                 r_fb.ghosttexture_valid = true;
6695                         }
6696                 }
6697                 else
6698                 {
6699                         // no r_fb.colortexture means we're rendering to the real fb
6700                         // we may still have to do view tint...
6701                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6702                         {
6703                                 // apply a color tint to the whole view
6704                                 R_ResetViewRendering2D(0, NULL, NULL);
6705                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6706                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6707                                 R_SetupShader_Generic_NoTexture(false, true);
6708                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6709                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6710                         }
6711                         break; // no screen processing, no bloom, skip it
6712                 }
6713
6714                 if (r_fb.bloomtexture[0])
6715                 {
6716                         // make the bloom texture
6717                         R_Bloom_MakeTexture();
6718                 }
6719
6720 #if _MSC_VER >= 1400
6721 #define sscanf sscanf_s
6722 #endif
6723                 memset(uservecs, 0, sizeof(uservecs));
6724                 if (r_glsl_postprocess_uservec1_enable.integer)
6725                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6726                 if (r_glsl_postprocess_uservec2_enable.integer)
6727                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6728                 if (r_glsl_postprocess_uservec3_enable.integer)
6729                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6730                 if (r_glsl_postprocess_uservec4_enable.integer)
6731                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6732
6733                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6734                 GL_Color(1, 1, 1, 1);
6735                 GL_BlendFunc(GL_ONE, GL_ZERO);
6736
6737                 switch(vid.renderpath)
6738                 {
6739                 case RENDERPATH_GL20:
6740                 case RENDERPATH_GLES2:
6741                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6742                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6743                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6744                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6745                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6746                         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]);
6747                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6748                         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]);
6749                         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]);
6750                         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]);
6751                         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]);
6752                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6753                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6754                         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);
6755                         break;
6756                 case RENDERPATH_D3D9:
6757 #ifdef SUPPORTD3D
6758                         // 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...
6759                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6760                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6761                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6762                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6763                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6764                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6765                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6766                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6767                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6768                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6769                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6770                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6771                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6772                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6773 #endif
6774                         break;
6775                 case RENDERPATH_D3D10:
6776                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6777                         break;
6778                 case RENDERPATH_D3D11:
6779                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6780                         break;
6781                 case RENDERPATH_SOFT:
6782                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6783                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6784                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6785                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6786                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6787                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6788                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6789                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6790                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6791                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6793                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6794                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6795                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6796                         break;
6797                 default:
6798                         break;
6799                 }
6800                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6801                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6802                 break;
6803         case RENDERPATH_GL11:
6804         case RENDERPATH_GL13:
6805         case RENDERPATH_GLES1:
6806                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6807                 {
6808                         // apply a color tint to the whole view
6809                         R_ResetViewRendering2D(0, NULL, NULL);
6810                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6811                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6812                         R_SetupShader_Generic_NoTexture(false, true);
6813                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6814                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6815                 }
6816                 break;
6817         }
6818 }
6819
6820 matrix4x4_t r_waterscrollmatrix;
6821
6822 void R_UpdateFog(void)
6823 {
6824         // Nehahra fog
6825         if (gamemode == GAME_NEHAHRA)
6826         {
6827                 if (gl_fogenable.integer)
6828                 {
6829                         r_refdef.oldgl_fogenable = true;
6830                         r_refdef.fog_density = gl_fogdensity.value;
6831                         r_refdef.fog_red = gl_fogred.value;
6832                         r_refdef.fog_green = gl_foggreen.value;
6833                         r_refdef.fog_blue = gl_fogblue.value;
6834                         r_refdef.fog_alpha = 1;
6835                         r_refdef.fog_start = 0;
6836                         r_refdef.fog_end = gl_skyclip.value;
6837                         r_refdef.fog_height = 1<<30;
6838                         r_refdef.fog_fadedepth = 128;
6839                 }
6840                 else if (r_refdef.oldgl_fogenable)
6841                 {
6842                         r_refdef.oldgl_fogenable = false;
6843                         r_refdef.fog_density = 0;
6844                         r_refdef.fog_red = 0;
6845                         r_refdef.fog_green = 0;
6846                         r_refdef.fog_blue = 0;
6847                         r_refdef.fog_alpha = 0;
6848                         r_refdef.fog_start = 0;
6849                         r_refdef.fog_end = 0;
6850                         r_refdef.fog_height = 1<<30;
6851                         r_refdef.fog_fadedepth = 128;
6852                 }
6853         }
6854
6855         // fog parms
6856         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6857         r_refdef.fog_start = max(0, r_refdef.fog_start);
6858         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6859
6860         if (r_refdef.fog_density && r_drawfog.integer)
6861         {
6862                 r_refdef.fogenabled = true;
6863                 // this is the point where the fog reaches 0.9986 alpha, which we
6864                 // consider a good enough cutoff point for the texture
6865                 // (0.9986 * 256 == 255.6)
6866                 if (r_fog_exp2.integer)
6867                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6868                 else
6869                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6870                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6871                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6872                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6873                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6874                         R_BuildFogHeightTexture();
6875                 // fog color was already set
6876                 // update the fog texture
6877                 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)
6878                         R_BuildFogTexture();
6879                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6880                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6881         }
6882         else
6883                 r_refdef.fogenabled = false;
6884
6885         // fog color
6886         if (r_refdef.fog_density)
6887         {
6888                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6889                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6890                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6891
6892                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6893                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6894                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6895                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6896
6897                 {
6898                         vec3_t fogvec;
6899                         VectorCopy(r_refdef.fogcolor, fogvec);
6900                         //   color.rgb *= ContrastBoost * SceneBrightness;
6901                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6902                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6903                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6904                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6905                 }
6906         }
6907 }
6908
6909 void R_UpdateVariables(void)
6910 {
6911         R_Textures_Frame();
6912
6913         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6914
6915         r_refdef.farclip = r_farclip_base.value;
6916         if (r_refdef.scene.worldmodel)
6917                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6918         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6919
6920         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6921                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6922         r_refdef.polygonfactor = 0;
6923         r_refdef.polygonoffset = 0;
6924         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6925         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6926
6927         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6928         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6929         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6930         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6931         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6932         if (FAKELIGHT_ENABLED)
6933         {
6934                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6935         }
6936         else if (r_refdef.scene.worldmodel)
6937         {
6938                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6939         }
6940         if (r_showsurfaces.integer)
6941         {
6942                 r_refdef.scene.rtworld = false;
6943                 r_refdef.scene.rtworldshadows = false;
6944                 r_refdef.scene.rtdlight = false;
6945                 r_refdef.scene.rtdlightshadows = false;
6946                 r_refdef.scene.lightmapintensity = 0;
6947         }
6948
6949         r_gpuskeletal = false;
6950         switch(vid.renderpath)
6951         {
6952         case RENDERPATH_GL20:
6953                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6954         case RENDERPATH_D3D9:
6955         case RENDERPATH_D3D10:
6956         case RENDERPATH_D3D11:
6957         case RENDERPATH_SOFT:
6958         case RENDERPATH_GLES2:
6959                 if(!vid_gammatables_trivial)
6960                 {
6961                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6962                         {
6963                                 // build GLSL gamma texture
6964 #define RAMPWIDTH 256
6965                                 unsigned short ramp[RAMPWIDTH * 3];
6966                                 unsigned char rampbgr[RAMPWIDTH][4];
6967                                 int i;
6968
6969                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6970
6971                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6972                                 for(i = 0; i < RAMPWIDTH; ++i)
6973                                 {
6974                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6975                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6976                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6977                                         rampbgr[i][3] = 0;
6978                                 }
6979                                 if (r_texture_gammaramps)
6980                                 {
6981                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6982                                 }
6983                                 else
6984                                 {
6985                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6986                                 }
6987                         }
6988                 }
6989                 else
6990                 {
6991                         // remove GLSL gamma texture
6992                 }
6993                 break;
6994         case RENDERPATH_GL11:
6995         case RENDERPATH_GL13:
6996         case RENDERPATH_GLES1:
6997                 break;
6998         }
6999 }
7000
7001 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7002 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7003 /*
7004 ================
7005 R_SelectScene
7006 ================
7007 */
7008 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7009         if( scenetype != r_currentscenetype ) {
7010                 // store the old scenetype
7011                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7012                 r_currentscenetype = scenetype;
7013                 // move in the new scene
7014                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7015         }
7016 }
7017
7018 /*
7019 ================
7020 R_GetScenePointer
7021 ================
7022 */
7023 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7024 {
7025         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7026         if( scenetype == r_currentscenetype ) {
7027                 return &r_refdef.scene;
7028         } else {
7029                 return &r_scenes_store[ scenetype ];
7030         }
7031 }
7032
7033 static int R_SortEntities_Compare(const void *ap, const void *bp)
7034 {
7035         const entity_render_t *a = *(const entity_render_t **)ap;
7036         const entity_render_t *b = *(const entity_render_t **)bp;
7037
7038         // 1. compare model
7039         if(a->model < b->model)
7040                 return -1;
7041         if(a->model > b->model)
7042                 return +1;
7043
7044         // 2. compare skin
7045         // TODO possibly calculate the REAL skinnum here first using
7046         // skinscenes?
7047         if(a->skinnum < b->skinnum)
7048                 return -1;
7049         if(a->skinnum > b->skinnum)
7050                 return +1;
7051
7052         // everything we compared is equal
7053         return 0;
7054 }
7055 static void R_SortEntities(void)
7056 {
7057         // below or equal 2 ents, sorting never gains anything
7058         if(r_refdef.scene.numentities <= 2)
7059                 return;
7060         // sort
7061         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7062 }
7063
7064 /*
7065 ================
7066 R_RenderView
7067 ================
7068 */
7069 int dpsoftrast_test;
7070 extern cvar_t r_shadow_bouncegrid;
7071 void R_RenderView(void)
7072 {
7073         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7074         int fbo;
7075         rtexture_t *depthtexture;
7076         rtexture_t *colortexture;
7077
7078         dpsoftrast_test = r_test.integer;
7079
7080         if (r_timereport_active)
7081                 R_TimeReport("start");
7082         r_textureframe++; // used only by R_GetCurrentTexture
7083         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7084
7085         if(R_CompileShader_CheckStaticParms())
7086                 R_GLSL_Restart_f();
7087
7088         if (!r_drawentities.integer)
7089                 r_refdef.scene.numentities = 0;
7090         else if (r_sortentities.integer)
7091                 R_SortEntities();
7092
7093         R_AnimCache_ClearCache();
7094
7095         /* adjust for stereo display */
7096         if(R_Stereo_Active())
7097         {
7098                 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);
7099                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7100         }
7101
7102         if (r_refdef.view.isoverlay)
7103         {
7104                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7105                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7106                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7107                 R_TimeReport("depthclear");
7108
7109                 r_refdef.view.showdebug = false;
7110
7111                 r_fb.water.enabled = false;
7112                 r_fb.water.numwaterplanes = 0;
7113
7114                 R_RenderScene(0, NULL, NULL);
7115
7116                 r_refdef.view.matrix = originalmatrix;
7117
7118                 CHECKGLERROR
7119                 return;
7120         }
7121
7122         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7123         {
7124                 r_refdef.view.matrix = originalmatrix;
7125                 return;
7126         }
7127
7128         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7129
7130         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7131                 // in sRGB fallback, behave similar to true sRGB: convert this
7132                 // value from linear to sRGB
7133                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7134
7135         R_RenderView_UpdateViewVectors();
7136
7137         R_Shadow_UpdateWorldLightSelection();
7138
7139         R_Bloom_StartFrame();
7140
7141         // apply bloom brightness offset
7142         if(r_fb.bloomtexture[0])
7143                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7144
7145         R_Water_StartFrame();
7146
7147         // now we probably have an fbo to render into
7148         fbo = r_fb.fbo;
7149         depthtexture = r_fb.depthtexture;
7150         colortexture = r_fb.colortexture;
7151
7152         CHECKGLERROR
7153         if (r_timereport_active)
7154                 R_TimeReport("viewsetup");
7155
7156         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7157
7158         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7159         {
7160                 R_ClearScreen(r_refdef.fogenabled);
7161                 if (r_timereport_active)
7162                         R_TimeReport("viewclear");
7163         }
7164         r_refdef.view.clear = true;
7165
7166         r_refdef.view.showdebug = true;
7167
7168         R_View_Update();
7169         if (r_timereport_active)
7170                 R_TimeReport("visibility");
7171
7172         R_AnimCache_CacheVisibleEntities();
7173         if (r_timereport_active)
7174                 R_TimeReport("animcache");
7175
7176         R_Shadow_UpdateBounceGridTexture();
7177         if (r_timereport_active && r_shadow_bouncegrid.integer)
7178                 R_TimeReport("bouncegrid");
7179
7180         r_fb.water.numwaterplanes = 0;
7181         if (r_fb.water.enabled)
7182                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7183
7184         R_RenderScene(fbo, depthtexture, colortexture);
7185         r_fb.water.numwaterplanes = 0;
7186
7187         R_BlendView(fbo, depthtexture, colortexture);
7188         if (r_timereport_active)
7189                 R_TimeReport("blendview");
7190
7191         GL_Scissor(0, 0, vid.width, vid.height);
7192         GL_ScissorTest(false);
7193
7194         r_refdef.view.matrix = originalmatrix;
7195
7196         CHECKGLERROR
7197 }
7198
7199 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7200 {
7201         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7202         {
7203                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7204                 if (r_timereport_active)
7205                         R_TimeReport("waterworld");
7206         }
7207
7208         // don't let sound skip if going slow
7209         if (r_refdef.scene.extraupdate)
7210                 S_ExtraUpdate ();
7211
7212         R_DrawModelsAddWaterPlanes();
7213         if (r_timereport_active)
7214                 R_TimeReport("watermodels");
7215
7216         if (r_fb.water.numwaterplanes)
7217         {
7218                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7219                 if (r_timereport_active)
7220                         R_TimeReport("waterscenes");
7221         }
7222 }
7223
7224 extern cvar_t cl_locs_show;
7225 static void R_DrawLocs(void);
7226 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7227 static void R_DrawModelDecals(void);
7228 extern cvar_t cl_decals_newsystem;
7229 extern qboolean r_shadow_usingdeferredprepass;
7230 extern int r_shadow_shadowmapatlas_modelshadows_size;
7231 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7232 {
7233         qboolean shadowmapping = false;
7234
7235         if (r_timereport_active)
7236                 R_TimeReport("beginscene");
7237
7238         r_refdef.stats[r_stat_renders]++;
7239
7240         R_UpdateFog();
7241
7242         // don't let sound skip if going slow
7243         if (r_refdef.scene.extraupdate)
7244                 S_ExtraUpdate ();
7245
7246         R_MeshQueue_BeginScene();
7247
7248         R_SkyStartFrame();
7249
7250         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);
7251
7252         if (r_timereport_active)
7253                 R_TimeReport("skystartframe");
7254
7255         if (cl.csqc_vidvars.drawworld)
7256         {
7257                 // don't let sound skip if going slow
7258                 if (r_refdef.scene.extraupdate)
7259                         S_ExtraUpdate ();
7260
7261                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7262                 {
7263                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7264                         if (r_timereport_active)
7265                                 R_TimeReport("worldsky");
7266                 }
7267
7268                 if (R_DrawBrushModelsSky() && r_timereport_active)
7269                         R_TimeReport("bmodelsky");
7270
7271                 if (skyrendermasked && skyrenderlater)
7272                 {
7273                         // we have to force off the water clipping plane while rendering sky
7274                         R_SetupView(false, fbo, depthtexture, colortexture);
7275                         R_Sky();
7276                         R_SetupView(true, fbo, depthtexture, colortexture);
7277                         if (r_timereport_active)
7278                                 R_TimeReport("sky");
7279                 }
7280         }
7281
7282         R_Shadow_PrepareModelShadows();
7283         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7284         if (r_timereport_active)
7285                 R_TimeReport("preparelights");
7286
7287         // render all the shadowmaps that will be used for this view
7288         shadowmapping = R_Shadow_ShadowMappingEnabled();
7289         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7290         {
7291                 R_Shadow_DrawShadowMaps();
7292                 if (r_timereport_active)
7293                         R_TimeReport("shadowmaps");
7294         }
7295
7296         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7297         if (r_shadow_usingdeferredprepass)
7298                 R_Shadow_DrawPrepass();
7299
7300         // now we begin the forward pass of the view render
7301         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7302         {
7303                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7304                 if (r_timereport_active)
7305                         R_TimeReport("worlddepth");
7306         }
7307         if (r_depthfirst.integer >= 2)
7308         {
7309                 R_DrawModelsDepth();
7310                 if (r_timereport_active)
7311                         R_TimeReport("modeldepth");
7312         }
7313
7314         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7315         {
7316                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7317                 if (r_timereport_active)
7318                         R_TimeReport("world");
7319         }
7320
7321         // don't let sound skip if going slow
7322         if (r_refdef.scene.extraupdate)
7323                 S_ExtraUpdate ();
7324
7325         R_DrawModels();
7326         if (r_timereport_active)
7327                 R_TimeReport("models");
7328
7329         // don't let sound skip if going slow
7330         if (r_refdef.scene.extraupdate)
7331                 S_ExtraUpdate ();
7332
7333         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7334         {
7335                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7336                 R_Shadow_DrawModelShadows();
7337                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7338                 // don't let sound skip if going slow
7339                 if (r_refdef.scene.extraupdate)
7340                         S_ExtraUpdate ();
7341         }
7342
7343         if (!r_shadow_usingdeferredprepass)
7344         {
7345                 R_Shadow_DrawLights();
7346                 if (r_timereport_active)
7347                         R_TimeReport("rtlights");
7348         }
7349
7350         // don't let sound skip if going slow
7351         if (r_refdef.scene.extraupdate)
7352                 S_ExtraUpdate ();
7353
7354         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7355         {
7356                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7357                 R_Shadow_DrawModelShadows();
7358                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7359                 // don't let sound skip if going slow
7360                 if (r_refdef.scene.extraupdate)
7361                         S_ExtraUpdate ();
7362         }
7363
7364         if (cl.csqc_vidvars.drawworld)
7365         {
7366                 if (cl_decals_newsystem.integer)
7367                 {
7368                         R_DrawModelDecals();
7369                         if (r_timereport_active)
7370                                 R_TimeReport("modeldecals");
7371                 }
7372                 else
7373                 {
7374                         R_DrawDecals();
7375                         if (r_timereport_active)
7376                                 R_TimeReport("decals");
7377                 }
7378
7379                 R_DrawParticles();
7380                 if (r_timereport_active)
7381                         R_TimeReport("particles");
7382
7383                 R_DrawExplosions();
7384                 if (r_timereport_active)
7385                         R_TimeReport("explosions");
7386         }
7387
7388         if (cl.csqc_loaded)
7389                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7390
7391         if (r_refdef.view.showdebug)
7392         {
7393                 if (cl_locs_show.integer)
7394                 {
7395                         R_DrawLocs();
7396                         if (r_timereport_active)
7397                                 R_TimeReport("showlocs");
7398                 }
7399
7400                 if (r_drawportals.integer)
7401                 {
7402                         R_DrawPortals();
7403                         if (r_timereport_active)
7404                                 R_TimeReport("portals");
7405                 }
7406
7407                 if (r_showbboxes_client.value > 0)
7408                 {
7409                         R_DrawEntityBBoxes(CLVM_prog);
7410                         if (r_timereport_active)
7411                                 R_TimeReport("clbboxes");
7412                 }
7413                 if (r_showbboxes.value > 0)
7414                 {
7415                         R_DrawEntityBBoxes(SVVM_prog);
7416                         if (r_timereport_active)
7417                                 R_TimeReport("svbboxes");
7418                 }
7419         }
7420
7421         if (r_transparent.integer)
7422         {
7423                 R_MeshQueue_RenderTransparent();
7424                 if (r_timereport_active)
7425                         R_TimeReport("drawtrans");
7426         }
7427
7428         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))
7429         {
7430                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7431                 if (r_timereport_active)
7432                         R_TimeReport("worlddebug");
7433                 R_DrawModelsDebug();
7434                 if (r_timereport_active)
7435                         R_TimeReport("modeldebug");
7436         }
7437
7438         if (cl.csqc_vidvars.drawworld)
7439         {
7440                 R_Shadow_DrawCoronas();
7441                 if (r_timereport_active)
7442                         R_TimeReport("coronas");
7443         }
7444
7445 #if 0
7446         {
7447                 GL_DepthTest(false);
7448                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7449                 GL_Color(1, 1, 1, 1);
7450                 qglBegin(GL_POLYGON);
7451                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7452                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7453                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7454                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7455                 qglEnd();
7456                 qglBegin(GL_POLYGON);
7457                 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]);
7458                 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]);
7459                 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]);
7460                 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]);
7461                 qglEnd();
7462                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7463         }
7464 #endif
7465
7466         // don't let sound skip if going slow
7467         if (r_refdef.scene.extraupdate)
7468                 S_ExtraUpdate ();
7469 }
7470
7471 static const unsigned short bboxelements[36] =
7472 {
7473         5, 1, 3, 5, 3, 7,
7474         6, 2, 0, 6, 0, 4,
7475         7, 3, 2, 7, 2, 6,
7476         4, 0, 1, 4, 1, 5,
7477         4, 5, 7, 4, 7, 6,
7478         1, 0, 2, 1, 2, 3,
7479 };
7480
7481 #define BBOXEDGES 13
7482 static const float bboxedges[BBOXEDGES][6] = 
7483 {
7484         // whole box
7485         { 0, 0, 0, 1, 1, 1 },
7486         // bottom edges
7487         { 0, 0, 0, 0, 1, 0 },
7488         { 0, 0, 0, 1, 0, 0 },
7489         { 0, 1, 0, 1, 1, 0 },
7490         { 1, 0, 0, 1, 1, 0 },
7491         // top edges
7492         { 0, 0, 1, 0, 1, 1 },
7493         { 0, 0, 1, 1, 0, 1 },
7494         { 0, 1, 1, 1, 1, 1 },
7495         { 1, 0, 1, 1, 1, 1 },
7496         // vertical edges
7497         { 0, 0, 0, 0, 0, 1 },
7498         { 1, 0, 0, 1, 0, 1 },
7499         { 0, 1, 0, 0, 1, 1 },
7500         { 1, 1, 0, 1, 1, 1 },
7501 };
7502
7503 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7504 {
7505         int numvertices = BBOXEDGES * 8;
7506         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7507         int numtriangles = BBOXEDGES * 12;
7508         unsigned short elements[BBOXEDGES * 36];
7509         int i, edge;
7510         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7511
7512         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7513
7514         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7515         GL_DepthMask(false);
7516         GL_DepthRange(0, 1);
7517         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7518
7519         for (edge = 0; edge < BBOXEDGES; edge++)
7520         {
7521                 for (i = 0; i < 3; i++)
7522                 {
7523                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7524                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7525                 }
7526                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7527                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7528                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7529                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7530                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7531                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7532                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7533                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7534                 for (i = 0; i < 36; i++)
7535                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7536         }
7537         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7538         if (r_refdef.fogenabled)
7539         {
7540                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7541                 {
7542                         f1 = RSurf_FogVertex(v);
7543                         f2 = 1 - f1;
7544                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7545                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7546                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7547                 }
7548         }
7549         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7550         R_Mesh_ResetTextureState();
7551         R_SetupShader_Generic_NoTexture(false, false);
7552         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7553 }
7554
7555 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7556 {
7557         // hacky overloading of the parameters
7558         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7559         int i;
7560         float color[4];
7561         prvm_edict_t *edict;
7562
7563         GL_CullFace(GL_NONE);
7564         R_SetupShader_Generic_NoTexture(false, false);
7565
7566         for (i = 0;i < numsurfaces;i++)
7567         {
7568                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7569                 switch ((int)PRVM_serveredictfloat(edict, solid))
7570                 {
7571                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7572                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7573                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7574                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7575                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7576                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7577                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7578                 }
7579                 if (prog == CLVM_prog)
7580                         color[3] *= r_showbboxes_client.value;
7581                 else
7582                         color[3] *= r_showbboxes.value;
7583                 color[3] = bound(0, color[3], 1);
7584                 GL_DepthTest(!r_showdisabledepthtest.integer);
7585                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7586         }
7587 }
7588
7589 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7590 {
7591         int i;
7592         prvm_edict_t *edict;
7593         vec3_t center;
7594
7595         if (prog == NULL)
7596                 return;
7597
7598         for (i = 0; i < prog->num_edicts; i++)
7599         {
7600                 edict = PRVM_EDICT_NUM(i);
7601                 if (edict->priv.server->free)
7602                         continue;
7603                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7604                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7605                         continue;
7606                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7607                         continue;
7608                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7609                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7610         }
7611 }
7612
7613 static const int nomodelelement3i[24] =
7614 {
7615         5, 2, 0,
7616         5, 1, 2,
7617         5, 0, 3,
7618         5, 3, 1,
7619         0, 2, 4,
7620         2, 1, 4,
7621         3, 0, 4,
7622         1, 3, 4
7623 };
7624
7625 static const unsigned short nomodelelement3s[24] =
7626 {
7627         5, 2, 0,
7628         5, 1, 2,
7629         5, 0, 3,
7630         5, 3, 1,
7631         0, 2, 4,
7632         2, 1, 4,
7633         3, 0, 4,
7634         1, 3, 4
7635 };
7636
7637 static const float nomodelvertex3f[6*3] =
7638 {
7639         -16,   0,   0,
7640          16,   0,   0,
7641           0, -16,   0,
7642           0,  16,   0,
7643           0,   0, -16,
7644           0,   0,  16
7645 };
7646
7647 static const float nomodelcolor4f[6*4] =
7648 {
7649         0.0f, 0.0f, 0.5f, 1.0f,
7650         0.0f, 0.0f, 0.5f, 1.0f,
7651         0.0f, 0.5f, 0.0f, 1.0f,
7652         0.0f, 0.5f, 0.0f, 1.0f,
7653         0.5f, 0.0f, 0.0f, 1.0f,
7654         0.5f, 0.0f, 0.0f, 1.0f
7655 };
7656
7657 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7658 {
7659         int i;
7660         float f1, f2, *c;
7661         float color4f[6*4];
7662
7663         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);
7664
7665         // this is only called once per entity so numsurfaces is always 1, and
7666         // surfacelist is always {0}, so this code does not handle batches
7667
7668         if (rsurface.ent_flags & RENDER_ADDITIVE)
7669         {
7670                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7671                 GL_DepthMask(false);
7672         }
7673         else if (ent->alpha < 1)
7674         {
7675                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7676                 GL_DepthMask(false);
7677         }
7678         else
7679         {
7680                 GL_BlendFunc(GL_ONE, GL_ZERO);
7681                 GL_DepthMask(true);
7682         }
7683         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7684         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7685         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7686         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7687         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7688         for (i = 0, c = color4f;i < 6;i++, c += 4)
7689         {
7690                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7691                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7692                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7693                 c[3] *= ent->alpha;
7694         }
7695         if (r_refdef.fogenabled)
7696         {
7697                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7698                 {
7699                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7700                         f2 = 1 - f1;
7701                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7702                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7703                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7704                 }
7705         }
7706 //      R_Mesh_ResetTextureState();
7707         R_SetupShader_Generic_NoTexture(false, false);
7708         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7709         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7710 }
7711
7712 void R_DrawNoModel(entity_render_t *ent)
7713 {
7714         vec3_t org;
7715         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7716         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7717                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7718         else
7719                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7720 }
7721
7722 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7723 {
7724         vec3_t right1, right2, diff, normal;
7725
7726         VectorSubtract (org2, org1, normal);
7727
7728         // calculate 'right' vector for start
7729         VectorSubtract (r_refdef.view.origin, org1, diff);
7730         CrossProduct (normal, diff, right1);
7731         VectorNormalize (right1);
7732
7733         // calculate 'right' vector for end
7734         VectorSubtract (r_refdef.view.origin, org2, diff);
7735         CrossProduct (normal, diff, right2);
7736         VectorNormalize (right2);
7737
7738         vert[ 0] = org1[0] + width * right1[0];
7739         vert[ 1] = org1[1] + width * right1[1];
7740         vert[ 2] = org1[2] + width * right1[2];
7741         vert[ 3] = org1[0] - width * right1[0];
7742         vert[ 4] = org1[1] - width * right1[1];
7743         vert[ 5] = org1[2] - width * right1[2];
7744         vert[ 6] = org2[0] - width * right2[0];
7745         vert[ 7] = org2[1] - width * right2[1];
7746         vert[ 8] = org2[2] - width * right2[2];
7747         vert[ 9] = org2[0] + width * right2[0];
7748         vert[10] = org2[1] + width * right2[1];
7749         vert[11] = org2[2] + width * right2[2];
7750 }
7751
7752 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)
7753 {
7754         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7755         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7756         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7757         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7758         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7759         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7760         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7761         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7762         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7763         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7764         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7765         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7766 }
7767
7768 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7769 {
7770         int i;
7771         float *vertex3f;
7772         float v[3];
7773         VectorSet(v, x, y, z);
7774         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7775                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7776                         break;
7777         if (i == mesh->numvertices)
7778         {
7779                 if (mesh->numvertices < mesh->maxvertices)
7780                 {
7781                         VectorCopy(v, vertex3f);
7782                         mesh->numvertices++;
7783                 }
7784                 return mesh->numvertices;
7785         }
7786         else
7787                 return i;
7788 }
7789
7790 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7791 {
7792         int i;
7793         int *e, element[3];
7794         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7795         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7796         e = mesh->element3i + mesh->numtriangles * 3;
7797         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7798         {
7799                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7800                 if (mesh->numtriangles < mesh->maxtriangles)
7801                 {
7802                         *e++ = element[0];
7803                         *e++ = element[1];
7804                         *e++ = element[2];
7805                         mesh->numtriangles++;
7806                 }
7807                 element[1] = element[2];
7808         }
7809 }
7810
7811 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7812 {
7813         int i;
7814         int *e, element[3];
7815         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7816         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7817         e = mesh->element3i + mesh->numtriangles * 3;
7818         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7819         {
7820                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7821                 if (mesh->numtriangles < mesh->maxtriangles)
7822                 {
7823                         *e++ = element[0];
7824                         *e++ = element[1];
7825                         *e++ = element[2];
7826                         mesh->numtriangles++;
7827                 }
7828                 element[1] = element[2];
7829         }
7830 }
7831
7832 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7833 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7834 {
7835         int planenum, planenum2;
7836         int w;
7837         int tempnumpoints;
7838         mplane_t *plane, *plane2;
7839         double maxdist;
7840         double temppoints[2][256*3];
7841         // figure out how large a bounding box we need to properly compute this brush
7842         maxdist = 0;
7843         for (w = 0;w < numplanes;w++)
7844                 maxdist = max(maxdist, fabs(planes[w].dist));
7845         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7846         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7847         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7848         {
7849                 w = 0;
7850                 tempnumpoints = 4;
7851                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7852                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7853                 {
7854                         if (planenum2 == planenum)
7855                                 continue;
7856                         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);
7857                         w = !w;
7858                 }
7859                 if (tempnumpoints < 3)
7860                         continue;
7861                 // generate elements forming a triangle fan for this polygon
7862                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7863         }
7864 }
7865
7866 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)
7867 {
7868         texturelayer_t *layer;
7869         layer = t->currentlayers + t->currentnumlayers++;
7870         layer->type = type;
7871         layer->depthmask = depthmask;
7872         layer->blendfunc1 = blendfunc1;
7873         layer->blendfunc2 = blendfunc2;
7874         layer->texture = texture;
7875         layer->texmatrix = *matrix;
7876         layer->color[0] = r;
7877         layer->color[1] = g;
7878         layer->color[2] = b;
7879         layer->color[3] = a;
7880 }
7881
7882 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7883 {
7884         if(parms[0] == 0 && parms[1] == 0)
7885                 return false;
7886         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7887                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7888                         return false;
7889         return true;
7890 }
7891
7892 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7893 {
7894         double index, f;
7895         index = parms[2] + rsurface.shadertime * parms[3];
7896         index -= floor(index);
7897         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7898         {
7899         default:
7900         case Q3WAVEFUNC_NONE:
7901         case Q3WAVEFUNC_NOISE:
7902         case Q3WAVEFUNC_COUNT:
7903                 f = 0;
7904                 break;
7905         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7906         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7907         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7908         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7909         case Q3WAVEFUNC_TRIANGLE:
7910                 index *= 4;
7911                 f = index - floor(index);
7912                 if (index < 1)
7913                 {
7914                         // f = f;
7915                 }
7916                 else if (index < 2)
7917                         f = 1 - f;
7918                 else if (index < 3)
7919                         f = -f;
7920                 else
7921                         f = -(1 - f);
7922                 break;
7923         }
7924         f = parms[0] + parms[1] * f;
7925         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7926                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7927         return (float) f;
7928 }
7929
7930 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7931 {
7932         int w, h, idx;
7933         float shadertime;
7934         float f;
7935         float offsetd[2];
7936         float tcmat[12];
7937         matrix4x4_t matrix, temp;
7938         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7939         // it's better to have one huge fixup every 9 hours than gradual
7940         // degradation over time which looks consistently bad after many hours.
7941         //
7942         // tcmod scroll in particular suffers from this degradation which can't be
7943         // effectively worked around even with floor() tricks because we don't
7944         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7945         // a workaround involving floor() would be incorrect anyway...
7946         shadertime = rsurface.shadertime;
7947         if (shadertime >= 32768.0f)
7948                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7949         switch(tcmod->tcmod)
7950         {
7951                 case Q3TCMOD_COUNT:
7952                 case Q3TCMOD_NONE:
7953                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7954                                 matrix = r_waterscrollmatrix;
7955                         else
7956                                 matrix = identitymatrix;
7957                         break;
7958                 case Q3TCMOD_ENTITYTRANSLATE:
7959                         // this is used in Q3 to allow the gamecode to control texcoord
7960                         // scrolling on the entity, which is not supported in darkplaces yet.
7961                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7962                         break;
7963                 case Q3TCMOD_ROTATE:
7964                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7965                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7966                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7967                         break;
7968                 case Q3TCMOD_SCALE:
7969                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7970                         break;
7971                 case Q3TCMOD_SCROLL:
7972                         // this particular tcmod is a "bug for bug" compatible one with regards to
7973                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7974                         // specifically did the wrapping and so we must mimic that...
7975                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7976                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7977                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7978                         break;
7979                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7980                         w = (int) tcmod->parms[0];
7981                         h = (int) tcmod->parms[1];
7982                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7983                         f = f - floor(f);
7984                         idx = (int) floor(f * w * h);
7985                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7986                         break;
7987                 case Q3TCMOD_STRETCH:
7988                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7989                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7990                         break;
7991                 case Q3TCMOD_TRANSFORM:
7992                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7993                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7994                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7995                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7996                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7997                         break;
7998                 case Q3TCMOD_TURBULENT:
7999                         // this is handled in the RSurf_PrepareVertices function
8000                         matrix = identitymatrix;
8001                         break;
8002         }
8003         temp = *texmatrix;
8004         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8005 }
8006
8007 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8008 {
8009         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8010         char name[MAX_QPATH];
8011         skinframe_t *skinframe;
8012         unsigned char pixels[296*194];
8013         strlcpy(cache->name, skinname, sizeof(cache->name));
8014         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8015         if (developer_loading.integer)
8016                 Con_Printf("loading %s\n", name);
8017         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8018         if (!skinframe || !skinframe->base)
8019         {
8020                 unsigned char *f;
8021                 fs_offset_t filesize;
8022                 skinframe = NULL;
8023                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8024                 if (f)
8025                 {
8026                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8027                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8028                         Mem_Free(f);
8029                 }
8030         }
8031         cache->skinframe = skinframe;
8032 }
8033
8034 texture_t *R_GetCurrentTexture(texture_t *t)
8035 {
8036         int i, q;
8037         const entity_render_t *ent = rsurface.entity;
8038         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8039         q3shaderinfo_layer_tcmod_t *tcmod;
8040         float specularscale = 0.0f;
8041
8042         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8043                 return t->currentframe;
8044         t->update_lastrenderframe = r_textureframe;
8045         t->update_lastrenderentity = (void *)ent;
8046
8047         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8048                 t->camera_entity = ent->entitynumber;
8049         else
8050                 t->camera_entity = 0;
8051
8052         // switch to an alternate material if this is a q1bsp animated material
8053         {
8054                 texture_t *texture = t;
8055                 int s = rsurface.ent_skinnum;
8056                 if ((unsigned int)s >= (unsigned int)model->numskins)
8057                         s = 0;
8058                 if (model->skinscenes)
8059                 {
8060                         if (model->skinscenes[s].framecount > 1)
8061                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8062                         else
8063                                 s = model->skinscenes[s].firstframe;
8064                 }
8065                 if (s > 0)
8066                         t = t + s * model->num_surfaces;
8067                 if (t->animated)
8068                 {
8069                         // use an alternate animation if the entity's frame is not 0,
8070                         // and only if the texture has an alternate animation
8071                         if (t->animated == 2) // q2bsp
8072                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8073                         else if (rsurface.ent_alttextures && t->anim_total[1])
8074                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8075                         else
8076                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8077                 }
8078                 texture->currentframe = t;
8079         }
8080
8081         // update currentskinframe to be a qw skin or animation frame
8082         if (rsurface.ent_qwskin >= 0)
8083         {
8084                 i = rsurface.ent_qwskin;
8085                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8086                 {
8087                         r_qwskincache_size = cl.maxclients;
8088                         if (r_qwskincache)
8089                                 Mem_Free(r_qwskincache);
8090                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8091                 }
8092                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8093                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8094                 t->currentskinframe = r_qwskincache[i].skinframe;
8095                 if (t->materialshaderpass && t->currentskinframe == NULL)
8096                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8097         }
8098         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8099                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8100         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8101                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8102
8103         t->currentmaterialflags = t->basematerialflags;
8104         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8105         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8106                 t->currentalpha *= r_wateralpha.value;
8107         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8108                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8109         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8110                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8111
8112         // decide on which type of lighting to use for this surface
8113         if (rsurface.entity->render_modellight_forced)
8114                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8115         if (rsurface.entity->render_rtlight_disabled)
8116                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8117         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8118         {
8119                 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8120                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8121                 for (q = 0; q < 3; q++)
8122                 {
8123                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8124                         t->render_modellight_lightdir[q] = q == 2;
8125                         t->render_modellight_ambient[q] = 1;
8126                         t->render_modellight_diffuse[q] = 0;
8127                         t->render_modellight_specular[q] = 0;
8128                         t->render_lightmap_ambient[q] = 0;
8129                         t->render_lightmap_diffuse[q] = 0;
8130                         t->render_lightmap_specular[q] = 0;
8131                         t->render_rtlight_diffuse[q] = 0;
8132                         t->render_rtlight_specular[q] = 0;
8133                 }
8134         }
8135         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8136         {
8137                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8138                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8139                 for (q = 0; q < 3; q++)
8140                 {
8141                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8142                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8143                         t->render_modellight_lightdir[q] = q == 2;
8144                         t->render_modellight_diffuse[q] = 0;
8145                         t->render_modellight_specular[q] = 0;
8146                         t->render_lightmap_ambient[q] = 0;
8147                         t->render_lightmap_diffuse[q] = 0;
8148                         t->render_lightmap_specular[q] = 0;
8149                         t->render_rtlight_diffuse[q] = 0;
8150                         t->render_rtlight_specular[q] = 0;
8151                 }
8152         }
8153         else if (FAKELIGHT_ENABLED)
8154         {
8155                 // no modellight if using fakelight for the map
8156                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8157                 for (q = 0; q < 3; q++)
8158                 {
8159                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8160                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8161                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8162                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8163                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8164                         t->render_lightmap_ambient[q] = 0;
8165                         t->render_lightmap_diffuse[q] = 0;
8166                         t->render_lightmap_specular[q] = 0;
8167                         t->render_rtlight_diffuse[q] = 0;
8168                         t->render_rtlight_specular[q] = 0;
8169                 }
8170         }
8171         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8172         {
8173                 // ambient + single direction light (modellight)
8174                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8175                 for (q = 0; q < 3; q++)
8176                 {
8177                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8178                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8179                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8180                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8181                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8182                         t->render_lightmap_ambient[q] = 0;
8183                         t->render_lightmap_diffuse[q] = 0;
8184                         t->render_lightmap_specular[q] = 0;
8185                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8186                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8187                 }
8188         }
8189         else
8190         {
8191                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8192                 for (q = 0; q < 3; q++)
8193                 {
8194                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8195                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8196                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8197                         t->render_modellight_diffuse[q] = 0;
8198                         t->render_modellight_specular[q] = 0;
8199                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8200                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8201                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8202                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8203                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8204                 }
8205         }
8206
8207         for (q = 0; q < 3; q++)
8208         {
8209                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8210                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8211         }
8212
8213         if (rsurface.ent_flags & RENDER_ADDITIVE)
8214                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8215         else if (t->currentalpha < 1)
8216                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8217         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8218         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8219                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8220         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8221                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8222         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8223                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8224         if (t->backgroundshaderpass)
8225                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8226         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8227         {
8228                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8229                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8230         }
8231         else
8232                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8233         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8234         {
8235                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8236                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8237         }
8238         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8239                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8240
8241         // there is no tcmod
8242         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8243         {
8244                 t->currenttexmatrix = r_waterscrollmatrix;
8245                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8246         }
8247         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8248         {
8249                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8250                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8251         }
8252
8253         if (t->materialshaderpass)
8254                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8255                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8256
8257         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8258         if (t->currentskinframe->qpixels)
8259                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8260         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8261         if (!t->basetexture)
8262                 t->basetexture = r_texture_notexture;
8263         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8264         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8265         t->nmaptexture = t->currentskinframe->nmap;
8266         if (!t->nmaptexture)
8267                 t->nmaptexture = r_texture_blanknormalmap;
8268         t->glosstexture = r_texture_black;
8269         t->glowtexture = t->currentskinframe->glow;
8270         t->fogtexture = t->currentskinframe->fog;
8271         t->reflectmasktexture = t->currentskinframe->reflect;
8272         if (t->backgroundshaderpass)
8273         {
8274                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8275                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8276                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8277                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8278                 t->backgroundglosstexture = r_texture_black;
8279                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8280                 if (!t->backgroundnmaptexture)
8281                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8282                 // make sure that if glow is going to be used, both textures are not NULL
8283                 if (!t->backgroundglowtexture && t->glowtexture)
8284                         t->backgroundglowtexture = r_texture_black;
8285                 if (!t->glowtexture && t->backgroundglowtexture)
8286                         t->glowtexture = r_texture_black;
8287         }
8288         else
8289         {
8290                 t->backgroundbasetexture = r_texture_white;
8291                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8292                 t->backgroundglosstexture = r_texture_black;
8293                 t->backgroundglowtexture = NULL;
8294         }
8295         t->specularpower = r_shadow_glossexponent.value;
8296         // TODO: store reference values for these in the texture?
8297         if (r_shadow_gloss.integer > 0)
8298         {
8299                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8300                 {
8301                         if (r_shadow_glossintensity.value > 0)
8302                         {
8303                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8304                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8305                                 specularscale = r_shadow_glossintensity.value;
8306                         }
8307                 }
8308                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8309                 {
8310                         t->glosstexture = r_texture_white;
8311                         t->backgroundglosstexture = r_texture_white;
8312                         specularscale = r_shadow_gloss2intensity.value;
8313                         t->specularpower = r_shadow_gloss2exponent.value;
8314                 }
8315         }
8316         specularscale *= t->specularscalemod;
8317         t->specularpower *= t->specularpowermod;
8318
8319         // lightmaps mode looks bad with dlights using actual texturing, so turn
8320         // off the colormap and glossmap, but leave the normalmap on as it still
8321         // accurately represents the shading involved
8322         if (gl_lightmaps.integer)
8323         {
8324                 t->basetexture = r_texture_grey128;
8325                 t->pantstexture = r_texture_black;
8326                 t->shirttexture = r_texture_black;
8327                 if (gl_lightmaps.integer < 2)
8328                         t->nmaptexture = r_texture_blanknormalmap;
8329                 t->glosstexture = r_texture_black;
8330                 t->glowtexture = NULL;
8331                 t->fogtexture = NULL;
8332                 t->reflectmasktexture = NULL;
8333                 t->backgroundbasetexture = NULL;
8334                 if (gl_lightmaps.integer < 2)
8335                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8336                 t->backgroundglosstexture = r_texture_black;
8337                 t->backgroundglowtexture = NULL;
8338                 specularscale = 0;
8339                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8340         }
8341
8342         if (specularscale != 1.0f)
8343         {
8344                 for (q = 0; q < 3; q++)
8345                 {
8346                         t->render_modellight_specular[q] *= specularscale;
8347                         t->render_lightmap_specular[q] *= specularscale;
8348                         t->render_rtlight_specular[q] *= specularscale;
8349                 }
8350         }
8351
8352         t->currentnumlayers = 0;
8353         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8354         {
8355                 int blendfunc1, blendfunc2;
8356                 qboolean depthmask;
8357                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8358                 {
8359                         blendfunc1 = GL_SRC_ALPHA;
8360                         blendfunc2 = GL_ONE;
8361                 }
8362                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8363                 {
8364                         blendfunc1 = GL_SRC_ALPHA;
8365                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8366                 }
8367                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8368                 {
8369                         blendfunc1 = t->customblendfunc[0];
8370                         blendfunc2 = t->customblendfunc[1];
8371                 }
8372                 else
8373                 {
8374                         blendfunc1 = GL_ONE;
8375                         blendfunc2 = GL_ZERO;
8376                 }
8377                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8378                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8379                 {
8380                         // basic lit geometry
8381                         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);
8382                         // add pants/shirt if needed
8383                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8384                                 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);
8385                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8386                                 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);
8387                 }
8388                 else
8389                 {
8390                         // basic lit geometry
8391                         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);
8392                         // add pants/shirt if needed
8393                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8394                                 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);
8395                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8396                                 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);
8397                         // now add ambient passes if needed
8398                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8399                         {
8400                                 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);
8401                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8402                                         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);
8403                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8404                                         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);
8405                         }
8406                 }
8407                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8408                         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);
8409                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8410                 {
8411                         // if this is opaque use alpha blend which will darken the earlier
8412                         // passes cheaply.
8413                         //
8414                         // if this is an alpha blended material, all the earlier passes
8415                         // were darkened by fog already, so we only need to add the fog
8416                         // color ontop through the fog mask texture
8417                         //
8418                         // if this is an additive blended material, all the earlier passes
8419                         // were darkened by fog already, and we should not add fog color
8420                         // (because the background was not darkened, there is no fog color
8421                         // that was lost behind it).
8422                         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);
8423                 }
8424         }
8425
8426         return t;
8427 }
8428
8429 rsurfacestate_t rsurface;
8430
8431 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8432 {
8433         dp_model_t *model = ent->model;
8434         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8435         //      return;
8436         rsurface.entity = (entity_render_t *)ent;
8437         rsurface.skeleton = ent->skeleton;
8438         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8439         rsurface.ent_skinnum = ent->skinnum;
8440         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;
8441         rsurface.ent_flags = ent->flags;
8442         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8443                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8444         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8445         rsurface.matrix = ent->matrix;
8446         rsurface.inversematrix = ent->inversematrix;
8447         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8448         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8449         R_EntityMatrix(&rsurface.matrix);
8450         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8451         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8452         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8453         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8454         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8455         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8456         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8457         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8458         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8459         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8460         if (ent->model->brush.submodel && !prepass)
8461         {
8462                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8463                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8464         }
8465         // if the animcache code decided it should use the shader path, skip the deform step
8466         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8467         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8468         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8469         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8470         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8471         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8472         {
8473                 if (ent->animcache_vertex3f)
8474                 {
8475                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8476                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8477                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8478                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8479                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8480                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8481                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8482                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8483                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8484                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8485                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8486                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8487                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8488                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8489                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8490                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8491                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8492                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8493                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8494                 }
8495                 else if (wanttangents)
8496                 {
8497                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8498                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8499                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8500                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8501                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8502                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8503                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8504                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8505                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8506                         rsurface.modelvertexmesh = NULL;
8507                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8508                         rsurface.modelvertexmesh_bufferoffset = 0;
8509                         rsurface.modelvertex3f_vertexbuffer = NULL;
8510                         rsurface.modelvertex3f_bufferoffset = 0;
8511                         rsurface.modelvertex3f_vertexbuffer = 0;
8512                         rsurface.modelvertex3f_bufferoffset = 0;
8513                         rsurface.modelsvector3f_vertexbuffer = 0;
8514                         rsurface.modelsvector3f_bufferoffset = 0;
8515                         rsurface.modeltvector3f_vertexbuffer = 0;
8516                         rsurface.modeltvector3f_bufferoffset = 0;
8517                         rsurface.modelnormal3f_vertexbuffer = 0;
8518                         rsurface.modelnormal3f_bufferoffset = 0;
8519                 }
8520                 else if (wantnormals)
8521                 {
8522                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8523                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8524                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8525                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8526                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8527                         rsurface.modelsvector3f = NULL;
8528                         rsurface.modeltvector3f = NULL;
8529                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8530                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8531                         rsurface.modelvertexmesh = NULL;
8532                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8533                         rsurface.modelvertexmesh_bufferoffset = 0;
8534                         rsurface.modelvertex3f_vertexbuffer = NULL;
8535                         rsurface.modelvertex3f_bufferoffset = 0;
8536                         rsurface.modelvertex3f_vertexbuffer = 0;
8537                         rsurface.modelvertex3f_bufferoffset = 0;
8538                         rsurface.modelsvector3f_vertexbuffer = 0;
8539                         rsurface.modelsvector3f_bufferoffset = 0;
8540                         rsurface.modeltvector3f_vertexbuffer = 0;
8541                         rsurface.modeltvector3f_bufferoffset = 0;
8542                         rsurface.modelnormal3f_vertexbuffer = 0;
8543                         rsurface.modelnormal3f_bufferoffset = 0;
8544                 }
8545                 else
8546                 {
8547                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8548                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8549                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8550                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8551                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8552                         rsurface.modelsvector3f = NULL;
8553                         rsurface.modeltvector3f = NULL;
8554                         rsurface.modelnormal3f = NULL;
8555                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8556                         rsurface.modelvertexmesh = NULL;
8557                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8558                         rsurface.modelvertexmesh_bufferoffset = 0;
8559                         rsurface.modelvertex3f_vertexbuffer = NULL;
8560                         rsurface.modelvertex3f_bufferoffset = 0;
8561                         rsurface.modelvertex3f_vertexbuffer = 0;
8562                         rsurface.modelvertex3f_bufferoffset = 0;
8563                         rsurface.modelsvector3f_vertexbuffer = 0;
8564                         rsurface.modelsvector3f_bufferoffset = 0;
8565                         rsurface.modeltvector3f_vertexbuffer = 0;
8566                         rsurface.modeltvector3f_bufferoffset = 0;
8567                         rsurface.modelnormal3f_vertexbuffer = 0;
8568                         rsurface.modelnormal3f_bufferoffset = 0;
8569                 }
8570                 rsurface.modelgeneratedvertex = true;
8571         }
8572         else
8573         {
8574                 if (rsurface.entityskeletaltransform3x4)
8575                 {
8576                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8577                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8578                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8579                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8580                 }
8581                 else
8582                 {
8583                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8584                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8585                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8586                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8587                 }
8588                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8589                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8590                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8591                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8592                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8593                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8594                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8595                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8596                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8597                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8598                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8599                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8600                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8601                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8602                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8603                 rsurface.modelgeneratedvertex = false;
8604         }
8605         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8606         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8607         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8608         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8609         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8610         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8611         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8612         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8613         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8614         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8615         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8616         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8617         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8618         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8619         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8620         rsurface.modelelement3i = model->surfmesh.data_element3i;
8621         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8622         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8623         rsurface.modelelement3s = model->surfmesh.data_element3s;
8624         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8625         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8626         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8627         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8628         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8629         rsurface.modelsurfaces = model->data_surfaces;
8630         rsurface.batchgeneratedvertex = false;
8631         rsurface.batchfirstvertex = 0;
8632         rsurface.batchnumvertices = 0;
8633         rsurface.batchfirsttriangle = 0;
8634         rsurface.batchnumtriangles = 0;
8635         rsurface.batchvertex3f  = NULL;
8636         rsurface.batchvertex3f_vertexbuffer = NULL;
8637         rsurface.batchvertex3f_bufferoffset = 0;
8638         rsurface.batchsvector3f = NULL;
8639         rsurface.batchsvector3f_vertexbuffer = NULL;
8640         rsurface.batchsvector3f_bufferoffset = 0;
8641         rsurface.batchtvector3f = NULL;
8642         rsurface.batchtvector3f_vertexbuffer = NULL;
8643         rsurface.batchtvector3f_bufferoffset = 0;
8644         rsurface.batchnormal3f  = NULL;
8645         rsurface.batchnormal3f_vertexbuffer = NULL;
8646         rsurface.batchnormal3f_bufferoffset = 0;
8647         rsurface.batchlightmapcolor4f = NULL;
8648         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8649         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8650         rsurface.batchtexcoordtexture2f = NULL;
8651         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8652         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8653         rsurface.batchtexcoordlightmap2f = NULL;
8654         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8655         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8656         rsurface.batchskeletalindex4ub = NULL;
8657         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8658         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8659         rsurface.batchskeletalweight4ub = NULL;
8660         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8661         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8662         rsurface.batchvertexmesh = NULL;
8663         rsurface.batchvertexmesh_vertexbuffer = NULL;
8664         rsurface.batchvertexmesh_bufferoffset = 0;
8665         rsurface.batchelement3i = NULL;
8666         rsurface.batchelement3i_indexbuffer = NULL;
8667         rsurface.batchelement3i_bufferoffset = 0;
8668         rsurface.batchelement3s = NULL;
8669         rsurface.batchelement3s_indexbuffer = NULL;
8670         rsurface.batchelement3s_bufferoffset = 0;
8671         rsurface.passcolor4f = NULL;
8672         rsurface.passcolor4f_vertexbuffer = NULL;
8673         rsurface.passcolor4f_bufferoffset = 0;
8674         rsurface.forcecurrenttextureupdate = false;
8675 }
8676
8677 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)
8678 {
8679         rsurface.entity = r_refdef.scene.worldentity;
8680         if (r != 1.0f || g != 1.0f || b != 1.0f || a != 1.0f) {
8681                 // HACK to provide a valid entity with modded colors to R_GetCurrentTexture.
8682                 // A better approach could be making this copy only once per frame.
8683                 static entity_render_t custom_entity;
8684                 int q;
8685                 custom_entity = *rsurface.entity;
8686                 for (q = 0; q < 3; ++q) {
8687                         float colormod = q == 0 ? r : q == 1 ? g : b;
8688                         custom_entity.render_fullbright[q] *= colormod;
8689                         custom_entity.render_modellight_ambient[q] *= colormod;
8690                         custom_entity.render_modellight_diffuse[q] *= colormod;
8691                         custom_entity.render_lightmap_ambient[q] *= colormod;
8692                         custom_entity.render_lightmap_diffuse[q] *= colormod;
8693                         custom_entity.render_rtlight_diffuse[q] *= colormod;
8694                 }
8695                 custom_entity.alpha *= a;
8696                 rsurface.entity = &custom_entity;
8697         }
8698         rsurface.skeleton = NULL;
8699         rsurface.ent_skinnum = 0;
8700         rsurface.ent_qwskin = -1;
8701         rsurface.ent_flags = entflags;
8702         rsurface.shadertime = r_refdef.scene.time - shadertime;
8703         rsurface.modelnumvertices = numvertices;
8704         rsurface.modelnumtriangles = numtriangles;
8705         rsurface.matrix = *matrix;
8706         rsurface.inversematrix = *inversematrix;
8707         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8708         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8709         R_EntityMatrix(&rsurface.matrix);
8710         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8711         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8712         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8713         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8714         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8715         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8716         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8717         rsurface.frameblend[0].lerp = 1;
8718         rsurface.ent_alttextures = false;
8719         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8720         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8721         rsurface.entityskeletaltransform3x4 = NULL;
8722         rsurface.entityskeletaltransform3x4buffer = NULL;
8723         rsurface.entityskeletaltransform3x4offset = 0;
8724         rsurface.entityskeletaltransform3x4size = 0;
8725         rsurface.entityskeletalnumtransforms = 0;
8726         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8727         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8728         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8729         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8730         if (wanttangents)
8731         {
8732                 rsurface.modelvertex3f = (float *)vertex3f;
8733                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8734                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8735                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8736         }
8737         else if (wantnormals)
8738         {
8739                 rsurface.modelvertex3f = (float *)vertex3f;
8740                 rsurface.modelsvector3f = NULL;
8741                 rsurface.modeltvector3f = NULL;
8742                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8743         }
8744         else
8745         {
8746                 rsurface.modelvertex3f = (float *)vertex3f;
8747                 rsurface.modelsvector3f = NULL;
8748                 rsurface.modeltvector3f = NULL;
8749                 rsurface.modelnormal3f = NULL;
8750         }
8751         rsurface.modelvertexmesh = NULL;
8752         rsurface.modelvertexmesh_vertexbuffer = NULL;
8753         rsurface.modelvertexmesh_bufferoffset = 0;
8754         rsurface.modelvertex3f_vertexbuffer = 0;
8755         rsurface.modelvertex3f_bufferoffset = 0;
8756         rsurface.modelsvector3f_vertexbuffer = 0;
8757         rsurface.modelsvector3f_bufferoffset = 0;
8758         rsurface.modeltvector3f_vertexbuffer = 0;
8759         rsurface.modeltvector3f_bufferoffset = 0;
8760         rsurface.modelnormal3f_vertexbuffer = 0;
8761         rsurface.modelnormal3f_bufferoffset = 0;
8762         rsurface.modelgeneratedvertex = true;
8763         rsurface.modellightmapcolor4f  = (float *)color4f;
8764         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8765         rsurface.modellightmapcolor4f_bufferoffset = 0;
8766         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8767         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8768         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8769         rsurface.modeltexcoordlightmap2f  = NULL;
8770         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8771         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8772         rsurface.modelskeletalindex4ub = NULL;
8773         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8774         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8775         rsurface.modelskeletalweight4ub = NULL;
8776         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8777         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8778         rsurface.modelelement3i = (int *)element3i;
8779         rsurface.modelelement3i_indexbuffer = NULL;
8780         rsurface.modelelement3i_bufferoffset = 0;
8781         rsurface.modelelement3s = (unsigned short *)element3s;
8782         rsurface.modelelement3s_indexbuffer = NULL;
8783         rsurface.modelelement3s_bufferoffset = 0;
8784         rsurface.modellightmapoffsets = NULL;
8785         rsurface.modelsurfaces = NULL;
8786         rsurface.batchgeneratedvertex = false;
8787         rsurface.batchfirstvertex = 0;
8788         rsurface.batchnumvertices = 0;
8789         rsurface.batchfirsttriangle = 0;
8790         rsurface.batchnumtriangles = 0;
8791         rsurface.batchvertex3f  = NULL;
8792         rsurface.batchvertex3f_vertexbuffer = NULL;
8793         rsurface.batchvertex3f_bufferoffset = 0;
8794         rsurface.batchsvector3f = NULL;
8795         rsurface.batchsvector3f_vertexbuffer = NULL;
8796         rsurface.batchsvector3f_bufferoffset = 0;
8797         rsurface.batchtvector3f = NULL;
8798         rsurface.batchtvector3f_vertexbuffer = NULL;
8799         rsurface.batchtvector3f_bufferoffset = 0;
8800         rsurface.batchnormal3f  = NULL;
8801         rsurface.batchnormal3f_vertexbuffer = NULL;
8802         rsurface.batchnormal3f_bufferoffset = 0;
8803         rsurface.batchlightmapcolor4f = NULL;
8804         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8805         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8806         rsurface.batchtexcoordtexture2f = NULL;
8807         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8808         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8809         rsurface.batchtexcoordlightmap2f = NULL;
8810         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8811         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8812         rsurface.batchskeletalindex4ub = NULL;
8813         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8814         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8815         rsurface.batchskeletalweight4ub = NULL;
8816         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8817         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8818         rsurface.batchvertexmesh = NULL;
8819         rsurface.batchvertexmesh_vertexbuffer = NULL;
8820         rsurface.batchvertexmesh_bufferoffset = 0;
8821         rsurface.batchelement3i = NULL;
8822         rsurface.batchelement3i_indexbuffer = NULL;
8823         rsurface.batchelement3i_bufferoffset = 0;
8824         rsurface.batchelement3s = NULL;
8825         rsurface.batchelement3s_indexbuffer = NULL;
8826         rsurface.batchelement3s_bufferoffset = 0;
8827         rsurface.passcolor4f = NULL;
8828         rsurface.passcolor4f_vertexbuffer = NULL;
8829         rsurface.passcolor4f_bufferoffset = 0;
8830         rsurface.forcecurrenttextureupdate = true;
8831
8832         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8833         {
8834                 if ((wantnormals || wanttangents) && !normal3f)
8835                 {
8836                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8837                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8838                 }
8839                 if (wanttangents && !svector3f)
8840                 {
8841                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8842                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8843                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8844                 }
8845         }
8846 }
8847
8848 float RSurf_FogPoint(const float *v)
8849 {
8850         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8851         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8852         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8853         float FogHeightFade = r_refdef.fogheightfade;
8854         float fogfrac;
8855         unsigned int fogmasktableindex;
8856         if (r_refdef.fogplaneviewabove)
8857                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8858         else
8859                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8860         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8861         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8862 }
8863
8864 float RSurf_FogVertex(const float *v)
8865 {
8866         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8867         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8868         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8869         float FogHeightFade = rsurface.fogheightfade;
8870         float fogfrac;
8871         unsigned int fogmasktableindex;
8872         if (r_refdef.fogplaneviewabove)
8873                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8874         else
8875                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8876         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8877         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8878 }
8879
8880 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8881 {
8882         int i;
8883         for (i = 0;i < numelements;i++)
8884                 outelement3i[i] = inelement3i[i] + adjust;
8885 }
8886
8887 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8888 extern cvar_t gl_vbo;
8889 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8890 {
8891         int deformindex;
8892         int firsttriangle;
8893         int numtriangles;
8894         int firstvertex;
8895         int endvertex;
8896         int numvertices;
8897         int surfacefirsttriangle;
8898         int surfacenumtriangles;
8899         int surfacefirstvertex;
8900         int surfaceendvertex;
8901         int surfacenumvertices;
8902         int batchnumsurfaces = texturenumsurfaces;
8903         int batchnumvertices;
8904         int batchnumtriangles;
8905         int needsupdate;
8906         int i, j;
8907         qboolean gaps;
8908         qboolean dynamicvertex;
8909         float amplitude;
8910         float animpos;
8911         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8912         float waveparms[4];
8913         unsigned char *ub;
8914         q3shaderinfo_deform_t *deform;
8915         const msurface_t *surface, *firstsurface;
8916         r_vertexmesh_t *vertexmesh;
8917         if (!texturenumsurfaces)
8918                 return;
8919         // find vertex range of this surface batch
8920         gaps = false;
8921         firstsurface = texturesurfacelist[0];
8922         firsttriangle = firstsurface->num_firsttriangle;
8923         batchnumvertices = 0;
8924         batchnumtriangles = 0;
8925         firstvertex = endvertex = firstsurface->num_firstvertex;
8926         for (i = 0;i < texturenumsurfaces;i++)
8927         {
8928                 surface = texturesurfacelist[i];
8929                 if (surface != firstsurface + i)
8930                         gaps = true;
8931                 surfacefirstvertex = surface->num_firstvertex;
8932                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8933                 surfacenumvertices = surface->num_vertices;
8934                 surfacenumtriangles = surface->num_triangles;
8935                 if (firstvertex > surfacefirstvertex)
8936                         firstvertex = surfacefirstvertex;
8937                 if (endvertex < surfaceendvertex)
8938                         endvertex = surfaceendvertex;
8939                 batchnumvertices += surfacenumvertices;
8940                 batchnumtriangles += surfacenumtriangles;
8941         }
8942
8943         r_refdef.stats[r_stat_batch_batches]++;
8944         if (gaps)
8945                 r_refdef.stats[r_stat_batch_withgaps]++;
8946         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8947         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8948         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8949
8950         // we now know the vertex range used, and if there are any gaps in it
8951         rsurface.batchfirstvertex = firstvertex;
8952         rsurface.batchnumvertices = endvertex - firstvertex;
8953         rsurface.batchfirsttriangle = firsttriangle;
8954         rsurface.batchnumtriangles = batchnumtriangles;
8955
8956         // this variable holds flags for which properties have been updated that
8957         // may require regenerating vertexmesh array...
8958         needsupdate = 0;
8959
8960         // check if any dynamic vertex processing must occur
8961         dynamicvertex = false;
8962
8963         // a cvar to force the dynamic vertex path to be taken, for debugging
8964         if (r_batch_debugdynamicvertexpath.integer)
8965         {
8966                 if (!dynamicvertex)
8967                 {
8968                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8969                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8970                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8971                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8972                 }
8973                 dynamicvertex = true;
8974         }
8975
8976         // if there is a chance of animated vertex colors, it's a dynamic batch
8977         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8978         {
8979                 if (!dynamicvertex)
8980                 {
8981                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8982                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8983                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8984                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8985                 }
8986                 dynamicvertex = true;
8987                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8988         }
8989
8990         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8991         {
8992                 switch (deform->deform)
8993                 {
8994                 default:
8995                 case Q3DEFORM_PROJECTIONSHADOW:
8996                 case Q3DEFORM_TEXT0:
8997                 case Q3DEFORM_TEXT1:
8998                 case Q3DEFORM_TEXT2:
8999                 case Q3DEFORM_TEXT3:
9000                 case Q3DEFORM_TEXT4:
9001                 case Q3DEFORM_TEXT5:
9002                 case Q3DEFORM_TEXT6:
9003                 case Q3DEFORM_TEXT7:
9004                 case Q3DEFORM_NONE:
9005                         break;
9006                 case Q3DEFORM_AUTOSPRITE:
9007                         if (!dynamicvertex)
9008                         {
9009                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9010                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9011                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9012                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9013                         }
9014                         dynamicvertex = true;
9015                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9016                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9017                         break;
9018                 case Q3DEFORM_AUTOSPRITE2:
9019                         if (!dynamicvertex)
9020                         {
9021                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9022                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9023                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9024                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9025                         }
9026                         dynamicvertex = true;
9027                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9028                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9029                         break;
9030                 case Q3DEFORM_NORMAL:
9031                         if (!dynamicvertex)
9032                         {
9033                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9034                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9035                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9036                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9037                         }
9038                         dynamicvertex = true;
9039                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9040                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9041                         break;
9042                 case Q3DEFORM_WAVE:
9043                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9044                                 break; // if wavefunc is a nop, ignore this transform
9045                         if (!dynamicvertex)
9046                         {
9047                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9048                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9049                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9050                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9051                         }
9052                         dynamicvertex = true;
9053                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9054                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9055                         break;
9056                 case Q3DEFORM_BULGE:
9057                         if (!dynamicvertex)
9058                         {
9059                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9060                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9061                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9062                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9063                         }
9064                         dynamicvertex = true;
9065                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9066                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9067                         break;
9068                 case Q3DEFORM_MOVE:
9069                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9070                                 break; // if wavefunc is a nop, ignore this transform
9071                         if (!dynamicvertex)
9072                         {
9073                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9074                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9075                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9076                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9077                         }
9078                         dynamicvertex = true;
9079                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9080                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9081                         break;
9082                 }
9083         }
9084         if (rsurface.texture->materialshaderpass)
9085         {
9086                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9087                 {
9088                 default:
9089                 case Q3TCGEN_TEXTURE:
9090                         break;
9091                 case Q3TCGEN_LIGHTMAP:
9092                         if (!dynamicvertex)
9093                         {
9094                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9095                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9096                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9097                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9098                         }
9099                         dynamicvertex = true;
9100                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9101                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9102                         break;
9103                 case Q3TCGEN_VECTOR:
9104                         if (!dynamicvertex)
9105                         {
9106                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9107                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9108                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9109                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9110                         }
9111                         dynamicvertex = true;
9112                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9113                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9114                         break;
9115                 case Q3TCGEN_ENVIRONMENT:
9116                         if (!dynamicvertex)
9117                         {
9118                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9119                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9120                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9121                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9122                         }
9123                         dynamicvertex = true;
9124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9125                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9126                         break;
9127                 }
9128                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9129                 {
9130                         if (!dynamicvertex)
9131                         {
9132                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9133                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9134                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9135                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9136                         }
9137                         dynamicvertex = true;
9138                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9139                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9140                 }
9141         }
9142
9143         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9144         {
9145                 if (!dynamicvertex)
9146                 {
9147                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9148                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9149                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9150                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9151                 }
9152                 dynamicvertex = true;
9153                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9154         }
9155
9156         // when the model data has no vertex buffer (dynamic mesh), we need to
9157         // eliminate gaps
9158         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9159                 batchneed |= BATCHNEED_NOGAPS;
9160
9161         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9162         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9163         // we ensure this by treating the vertex batch as dynamic...
9164         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9165         {
9166                 if (!dynamicvertex)
9167                 {
9168                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9169                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9170                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9171                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9172                 }
9173                 dynamicvertex = true;
9174         }
9175
9176         if (dynamicvertex)
9177         {
9178                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9179                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9180                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9181                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9182                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9183                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9184                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9185                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9186         }
9187
9188         // if needsupdate, we have to do a dynamic vertex batch for sure
9189         if (needsupdate & batchneed)
9190         {
9191                 if (!dynamicvertex)
9192                 {
9193                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9194                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9195                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9196                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9197                 }
9198                 dynamicvertex = true;
9199         }
9200
9201         // see if we need to build vertexmesh from arrays
9202         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9203         {
9204                 if (!dynamicvertex)
9205                 {
9206                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9207                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9208                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9209                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9210                 }
9211                 dynamicvertex = true;
9212         }
9213
9214         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9215         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9216                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9217
9218         rsurface.batchvertex3f = rsurface.modelvertex3f;
9219         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9220         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9221         rsurface.batchsvector3f = rsurface.modelsvector3f;
9222         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9223         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9224         rsurface.batchtvector3f = rsurface.modeltvector3f;
9225         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9226         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9227         rsurface.batchnormal3f = rsurface.modelnormal3f;
9228         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9229         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9230         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9231         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9232         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9233         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9234         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9235         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9236         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9237         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9238         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9239         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9240         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9241         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9242         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9243         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9244         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9245         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9246         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9247         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9248         rsurface.batchelement3i = rsurface.modelelement3i;
9249         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9250         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9251         rsurface.batchelement3s = rsurface.modelelement3s;
9252         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9253         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9254         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9255         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9256         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9257         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9258         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9259
9260         // if any dynamic vertex processing has to occur in software, we copy the
9261         // entire surface list together before processing to rebase the vertices
9262         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9263         //
9264         // if any gaps exist and we do not have a static vertex buffer, we have to
9265         // copy the surface list together to avoid wasting upload bandwidth on the
9266         // vertices in the gaps.
9267         //
9268         // if gaps exist and we have a static vertex buffer, we can choose whether
9269         // to combine the index buffer ranges into one dynamic index buffer or
9270         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9271         //
9272         // in many cases the batch is reduced to one draw call.
9273
9274         rsurface.batchmultidraw = false;
9275         rsurface.batchmultidrawnumsurfaces = 0;
9276         rsurface.batchmultidrawsurfacelist = NULL;
9277
9278         if (!dynamicvertex)
9279         {
9280                 // static vertex data, just set pointers...
9281                 rsurface.batchgeneratedvertex = false;
9282                 // if there are gaps, we want to build a combined index buffer,
9283                 // otherwise use the original static buffer with an appropriate offset
9284                 if (gaps)
9285                 {
9286                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9287                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9288                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9289                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9290                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9291                         {
9292                                 rsurface.batchmultidraw = true;
9293                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9294                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9295                                 return;
9296                         }
9297                         // build a new triangle elements array for this batch
9298                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9299                         rsurface.batchfirsttriangle = 0;
9300                         numtriangles = 0;
9301                         for (i = 0;i < texturenumsurfaces;i++)
9302                         {
9303                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9304                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9305                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9306                                 numtriangles += surfacenumtriangles;
9307                         }
9308                         rsurface.batchelement3i_indexbuffer = NULL;
9309                         rsurface.batchelement3i_bufferoffset = 0;
9310                         rsurface.batchelement3s = NULL;
9311                         rsurface.batchelement3s_indexbuffer = NULL;
9312                         rsurface.batchelement3s_bufferoffset = 0;
9313                         if (endvertex <= 65536)
9314                         {
9315                                 // make a 16bit (unsigned short) index array if possible
9316                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9317                                 for (i = 0;i < numtriangles*3;i++)
9318                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9319                         }
9320                         // upload buffer data for the copytriangles batch
9321                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9322                         {
9323                                 if (rsurface.batchelement3s)
9324                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9325                                 else if (rsurface.batchelement3i)
9326                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9327                         }
9328                 }
9329                 else
9330                 {
9331                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9332                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9333                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9334                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9335                 }
9336                 return;
9337         }
9338
9339         // something needs software processing, do it for real...
9340         // we only directly handle separate array data in this case and then
9341         // generate interleaved data if needed...
9342         rsurface.batchgeneratedvertex = true;
9343         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9344         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9345         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9346         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9347
9348         // now copy the vertex data into a combined array and make an index array
9349         // (this is what Quake3 does all the time)
9350         // we also apply any skeletal animation here that would have been done in
9351         // the vertex shader, because most of the dynamic vertex animation cases
9352         // need actual vertex positions and normals
9353         //if (dynamicvertex)
9354         {
9355                 rsurface.batchvertexmesh = NULL;
9356                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9357                 rsurface.batchvertexmesh_bufferoffset = 0;
9358                 rsurface.batchvertex3f = NULL;
9359                 rsurface.batchvertex3f_vertexbuffer = NULL;
9360                 rsurface.batchvertex3f_bufferoffset = 0;
9361                 rsurface.batchsvector3f = NULL;
9362                 rsurface.batchsvector3f_vertexbuffer = NULL;
9363                 rsurface.batchsvector3f_bufferoffset = 0;
9364                 rsurface.batchtvector3f = NULL;
9365                 rsurface.batchtvector3f_vertexbuffer = NULL;
9366                 rsurface.batchtvector3f_bufferoffset = 0;
9367                 rsurface.batchnormal3f = NULL;
9368                 rsurface.batchnormal3f_vertexbuffer = NULL;
9369                 rsurface.batchnormal3f_bufferoffset = 0;
9370                 rsurface.batchlightmapcolor4f = NULL;
9371                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9372                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9373                 rsurface.batchtexcoordtexture2f = NULL;
9374                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9375                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9376                 rsurface.batchtexcoordlightmap2f = NULL;
9377                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9378                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9379                 rsurface.batchskeletalindex4ub = NULL;
9380                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9381                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9382                 rsurface.batchskeletalweight4ub = NULL;
9383                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9384                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9385                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9386                 rsurface.batchelement3i_indexbuffer = NULL;
9387                 rsurface.batchelement3i_bufferoffset = 0;
9388                 rsurface.batchelement3s = NULL;
9389                 rsurface.batchelement3s_indexbuffer = NULL;
9390                 rsurface.batchelement3s_bufferoffset = 0;
9391                 rsurface.batchskeletaltransform3x4buffer = NULL;
9392                 rsurface.batchskeletaltransform3x4offset = 0;
9393                 rsurface.batchskeletaltransform3x4size = 0;
9394                 // we'll only be setting up certain arrays as needed
9395                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9396                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9397                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9398                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9399                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9400                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9401                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9402                 {
9403                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9404                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9405                 }
9406                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9407                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9408                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9409                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9410                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9411                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9412                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9413                 {
9414                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9415                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9416                 }
9417                 numvertices = 0;
9418                 numtriangles = 0;
9419                 for (i = 0;i < texturenumsurfaces;i++)
9420                 {
9421                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9422                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9423                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9424                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9425                         // copy only the data requested
9426                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9427                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9428                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9429                         {
9430                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9431                                 {
9432                                         if (rsurface.batchvertex3f)
9433                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9434                                         else
9435                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9436                                 }
9437                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9438                                 {
9439                                         if (rsurface.modelnormal3f)
9440                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9441                                         else
9442                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9443                                 }
9444                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9445                                 {
9446                                         if (rsurface.modelsvector3f)
9447                                         {
9448                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9449                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9450                                         }
9451                                         else
9452                                         {
9453                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9454                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9455                                         }
9456                                 }
9457                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9458                                 {
9459                                         if (rsurface.modellightmapcolor4f)
9460                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9461                                         else
9462                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9463                                 }
9464                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9465                                 {
9466                                         if (rsurface.modeltexcoordtexture2f)
9467                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9468                                         else
9469                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9470                                 }
9471                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9472                                 {
9473                                         if (rsurface.modeltexcoordlightmap2f)
9474                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9475                                         else
9476                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9477                                 }
9478                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9479                                 {
9480                                         if (rsurface.modelskeletalindex4ub)
9481                                         {
9482                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9483                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9484                                         }
9485                                         else
9486                                         {
9487                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9488                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9489                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9490                                                 for (j = 0;j < surfacenumvertices;j++)
9491                                                         ub[j*4] = 255;
9492                                         }
9493                                 }
9494                         }
9495                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9496                         numvertices += surfacenumvertices;
9497                         numtriangles += surfacenumtriangles;
9498                 }
9499
9500                 // generate a 16bit index array as well if possible
9501                 // (in general, dynamic batches fit)
9502                 if (numvertices <= 65536)
9503                 {
9504                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9505                         for (i = 0;i < numtriangles*3;i++)
9506                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9507                 }
9508
9509                 // since we've copied everything, the batch now starts at 0
9510                 rsurface.batchfirstvertex = 0;
9511                 rsurface.batchnumvertices = batchnumvertices;
9512                 rsurface.batchfirsttriangle = 0;
9513                 rsurface.batchnumtriangles = batchnumtriangles;
9514         }
9515
9516         // apply skeletal animation that would have been done in the vertex shader
9517         if (rsurface.batchskeletaltransform3x4)
9518         {
9519                 const unsigned char *si;
9520                 const unsigned char *sw;
9521                 const float *t[4];
9522                 const float *b = rsurface.batchskeletaltransform3x4;
9523                 float *vp, *vs, *vt, *vn;
9524                 float w[4];
9525                 float m[3][4], n[3][4];
9526                 float tp[3], ts[3], tt[3], tn[3];
9527                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9528                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9529                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9530                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9531                 si = rsurface.batchskeletalindex4ub;
9532                 sw = rsurface.batchskeletalweight4ub;
9533                 vp = rsurface.batchvertex3f;
9534                 vs = rsurface.batchsvector3f;
9535                 vt = rsurface.batchtvector3f;
9536                 vn = rsurface.batchnormal3f;
9537                 memset(m[0], 0, sizeof(m));
9538                 memset(n[0], 0, sizeof(n));
9539                 for (i = 0;i < batchnumvertices;i++)
9540                 {
9541                         t[0] = b + si[0]*12;
9542                         if (sw[0] == 255)
9543                         {
9544                                 // common case - only one matrix
9545                                 m[0][0] = t[0][ 0];
9546                                 m[0][1] = t[0][ 1];
9547                                 m[0][2] = t[0][ 2];
9548                                 m[0][3] = t[0][ 3];
9549                                 m[1][0] = t[0][ 4];
9550                                 m[1][1] = t[0][ 5];
9551                                 m[1][2] = t[0][ 6];
9552                                 m[1][3] = t[0][ 7];
9553                                 m[2][0] = t[0][ 8];
9554                                 m[2][1] = t[0][ 9];
9555                                 m[2][2] = t[0][10];
9556                                 m[2][3] = t[0][11];
9557                         }
9558                         else if (sw[2] + sw[3])
9559                         {
9560                                 // blend 4 matrices
9561                                 t[1] = b + si[1]*12;
9562                                 t[2] = b + si[2]*12;
9563                                 t[3] = b + si[3]*12;
9564                                 w[0] = sw[0] * (1.0f / 255.0f);
9565                                 w[1] = sw[1] * (1.0f / 255.0f);
9566                                 w[2] = sw[2] * (1.0f / 255.0f);
9567                                 w[3] = sw[3] * (1.0f / 255.0f);
9568                                 // blend the matrices
9569                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9570                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9571                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9572                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9573                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9574                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9575                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9576                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9577                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9578                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9579                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9580                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9581                         }
9582                         else
9583                         {
9584                                 // blend 2 matrices
9585                                 t[1] = b + si[1]*12;
9586                                 w[0] = sw[0] * (1.0f / 255.0f);
9587                                 w[1] = sw[1] * (1.0f / 255.0f);
9588                                 // blend the matrices
9589                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9590                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9591                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9592                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9593                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9594                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9595                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9596                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9597                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9598                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9599                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9600                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9601                         }
9602                         si += 4;
9603                         sw += 4;
9604                         // modify the vertex
9605                         VectorCopy(vp, tp);
9606                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9607                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9608                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9609                         vp += 3;
9610                         if (vn)
9611                         {
9612                                 // the normal transformation matrix is a set of cross products...
9613                                 CrossProduct(m[1], m[2], n[0]);
9614                                 CrossProduct(m[2], m[0], n[1]);
9615                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9616                                 VectorCopy(vn, tn);
9617                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9618                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9619                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9620                                 VectorNormalize(vn);
9621                                 vn += 3;
9622                                 if (vs)
9623                                 {
9624                                         VectorCopy(vs, ts);
9625                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9626                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9627                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9628                                         VectorNormalize(vs);
9629                                         vs += 3;
9630                                         VectorCopy(vt, tt);
9631                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9632                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9633                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9634                                         VectorNormalize(vt);
9635                                         vt += 3;
9636                                 }
9637                         }
9638                 }
9639                 rsurface.batchskeletaltransform3x4 = NULL;
9640                 rsurface.batchskeletalnumtransforms = 0;
9641         }
9642
9643         // q1bsp surfaces rendered in vertex color mode have to have colors
9644         // calculated based on lightstyles
9645         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9646         {
9647                 // generate color arrays for the surfaces in this list
9648                 int c[4];
9649                 int scale;
9650                 int size3;
9651                 const int *offsets;
9652                 const unsigned char *lm;
9653                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9654                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9655                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9656                 numvertices = 0;
9657                 for (i = 0;i < texturenumsurfaces;i++)
9658                 {
9659                         surface = texturesurfacelist[i];
9660                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9661                         surfacenumvertices = surface->num_vertices;
9662                         if (surface->lightmapinfo->samples)
9663                         {
9664                                 for (j = 0;j < surfacenumvertices;j++)
9665                                 {
9666                                         lm = surface->lightmapinfo->samples + offsets[j];
9667                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9668                                         VectorScale(lm, scale, c);
9669                                         if (surface->lightmapinfo->styles[1] != 255)
9670                                         {
9671                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9672                                                 lm += size3;
9673                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9674                                                 VectorMA(c, scale, lm, c);
9675                                                 if (surface->lightmapinfo->styles[2] != 255)
9676                                                 {
9677                                                         lm += size3;
9678                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9679                                                         VectorMA(c, scale, lm, c);
9680                                                         if (surface->lightmapinfo->styles[3] != 255)
9681                                                         {
9682                                                                 lm += size3;
9683                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9684                                                                 VectorMA(c, scale, lm, c);
9685                                                         }
9686                                                 }
9687                                         }
9688                                         c[0] >>= 7;
9689                                         c[1] >>= 7;
9690                                         c[2] >>= 7;
9691                                         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);
9692                                         numvertices++;
9693                                 }
9694                         }
9695                         else
9696                         {
9697                                 for (j = 0;j < surfacenumvertices;j++)
9698                                 {
9699                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9700                                         numvertices++;
9701                                 }
9702                         }
9703                 }
9704         }
9705
9706         // if vertices are deformed (sprite flares and things in maps, possibly
9707         // water waves, bulges and other deformations), modify the copied vertices
9708         // in place
9709         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9710         {
9711                 float scale;
9712                 switch (deform->deform)
9713                 {
9714                 default:
9715                 case Q3DEFORM_PROJECTIONSHADOW:
9716                 case Q3DEFORM_TEXT0:
9717                 case Q3DEFORM_TEXT1:
9718                 case Q3DEFORM_TEXT2:
9719                 case Q3DEFORM_TEXT3:
9720                 case Q3DEFORM_TEXT4:
9721                 case Q3DEFORM_TEXT5:
9722                 case Q3DEFORM_TEXT6:
9723                 case Q3DEFORM_TEXT7:
9724                 case Q3DEFORM_NONE:
9725                         break;
9726                 case Q3DEFORM_AUTOSPRITE:
9727                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9728                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9729                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9730                         VectorNormalize(newforward);
9731                         VectorNormalize(newright);
9732                         VectorNormalize(newup);
9733 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9734 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9735 //                      rsurface.batchvertex3f_bufferoffset = 0;
9736 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9737 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9738 //                      rsurface.batchsvector3f_bufferoffset = 0;
9739 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9740 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9741 //                      rsurface.batchtvector3f_bufferoffset = 0;
9742 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9743 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9744 //                      rsurface.batchnormal3f_bufferoffset = 0;
9745                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9746                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9747                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9748                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
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                         // a single autosprite surface can contain multiple sprites...
9751                         for (j = 0;j < batchnumvertices - 3;j += 4)
9752                         {
9753                                 VectorClear(center);
9754                                 for (i = 0;i < 4;i++)
9755                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9756                                 VectorScale(center, 0.25f, center);
9757                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9758                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9759                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9760                                 for (i = 0;i < 4;i++)
9761                                 {
9762                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9763                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9764                                 }
9765                         }
9766                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9767                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9768                         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);
9769                         break;
9770                 case Q3DEFORM_AUTOSPRITE2:
9771                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9772                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9773                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9774                         VectorNormalize(newforward);
9775                         VectorNormalize(newright);
9776                         VectorNormalize(newup);
9777 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9778 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9779 //                      rsurface.batchvertex3f_bufferoffset = 0;
9780                         {
9781                                 const float *v1, *v2;
9782                                 vec3_t start, end;
9783                                 float f, l;
9784                                 struct
9785                                 {
9786                                         float length2;
9787                                         const float *v1;
9788                                         const float *v2;
9789                                 }
9790                                 shortest[2];
9791                                 memset(shortest, 0, sizeof(shortest));
9792                                 // a single autosprite surface can contain multiple sprites...
9793                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9794                                 {
9795                                         VectorClear(center);
9796                                         for (i = 0;i < 4;i++)
9797                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9798                                         VectorScale(center, 0.25f, center);
9799                                         // find the two shortest edges, then use them to define the
9800                                         // axis vectors for rotating around the central axis
9801                                         for (i = 0;i < 6;i++)
9802                                         {
9803                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9804                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9805                                                 l = VectorDistance2(v1, v2);
9806                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9807                                                 if (v1[2] != v2[2])
9808                                                         l += (1.0f / 1024.0f);
9809                                                 if (shortest[0].length2 > l || i == 0)
9810                                                 {
9811                                                         shortest[1] = shortest[0];
9812                                                         shortest[0].length2 = l;
9813                                                         shortest[0].v1 = v1;
9814                                                         shortest[0].v2 = v2;
9815                                                 }
9816                                                 else if (shortest[1].length2 > l || i == 1)
9817                                                 {
9818                                                         shortest[1].length2 = l;
9819                                                         shortest[1].v1 = v1;
9820                                                         shortest[1].v2 = v2;
9821                                                 }
9822                                         }
9823                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9824                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9825                                         // this calculates the right vector from the shortest edge
9826                                         // and the up vector from the edge midpoints
9827                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9828                                         VectorNormalize(right);
9829                                         VectorSubtract(end, start, up);
9830                                         VectorNormalize(up);
9831                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9832                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9833                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9834                                         VectorNegate(forward, forward);
9835                                         VectorReflect(forward, 0, up, forward);
9836                                         VectorNormalize(forward);
9837                                         CrossProduct(up, forward, newright);
9838                                         VectorNormalize(newright);
9839                                         // rotate the quad around the up axis vector, this is made
9840                                         // especially easy by the fact we know the quad is flat,
9841                                         // so we only have to subtract the center position and
9842                                         // measure distance along the right vector, and then
9843                                         // multiply that by the newright vector and add back the
9844                                         // center position
9845                                         // we also need to subtract the old position to undo the
9846                                         // displacement from the center, which we do with a
9847                                         // DotProduct, the subtraction/addition of center is also
9848                                         // optimized into DotProducts here
9849                                         l = DotProduct(right, center);
9850                                         for (i = 0;i < 4;i++)
9851                                         {
9852                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9853                                                 f = DotProduct(right, v1) - l;
9854                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9855                                         }
9856                                 }
9857                         }
9858                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9859                         {
9860 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9861 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9862 //                              rsurface.batchnormal3f_bufferoffset = 0;
9863                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9864                         }
9865                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9866                         {
9867 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9868 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9869 //                              rsurface.batchsvector3f_bufferoffset = 0;
9870 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9871 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9872 //                              rsurface.batchtvector3f_bufferoffset = 0;
9873                                 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);
9874                         }
9875                         break;
9876                 case Q3DEFORM_NORMAL:
9877                         // deform the normals to make reflections wavey
9878                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9879                         rsurface.batchnormal3f_vertexbuffer = NULL;
9880                         rsurface.batchnormal3f_bufferoffset = 0;
9881                         for (j = 0;j < batchnumvertices;j++)
9882                         {
9883                                 float vertex[3];
9884                                 float *normal = rsurface.batchnormal3f + 3*j;
9885                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9886                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9887                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9888                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9889                                 VectorNormalize(normal);
9890                         }
9891                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9892                         {
9893 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9894 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9895 //                              rsurface.batchsvector3f_bufferoffset = 0;
9896 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9897 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9898 //                              rsurface.batchtvector3f_bufferoffset = 0;
9899                                 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);
9900                         }
9901                         break;
9902                 case Q3DEFORM_WAVE:
9903                         // deform vertex array to make wavey water and flags and such
9904                         waveparms[0] = deform->waveparms[0];
9905                         waveparms[1] = deform->waveparms[1];
9906                         waveparms[2] = deform->waveparms[2];
9907                         waveparms[3] = deform->waveparms[3];
9908                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9909                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9910                         // this is how a divisor of vertex influence on deformation
9911                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9912                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9913 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9914 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9915 //                      rsurface.batchvertex3f_bufferoffset = 0;
9916 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9917 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9918 //                      rsurface.batchnormal3f_bufferoffset = 0;
9919                         for (j = 0;j < batchnumvertices;j++)
9920                         {
9921                                 // if the wavefunc depends on time, evaluate it per-vertex
9922                                 if (waveparms[3])
9923                                 {
9924                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9925                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9926                                 }
9927                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9928                         }
9929                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9930                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9931                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9932                         {
9933 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9934 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9935 //                              rsurface.batchsvector3f_bufferoffset = 0;
9936 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9937 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9938 //                              rsurface.batchtvector3f_bufferoffset = 0;
9939                                 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);
9940                         }
9941                         break;
9942                 case Q3DEFORM_BULGE:
9943                         // deform vertex array to make the surface have moving bulges
9944 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9945 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9946 //                      rsurface.batchvertex3f_bufferoffset = 0;
9947 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9948 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9949 //                      rsurface.batchnormal3f_bufferoffset = 0;
9950                         for (j = 0;j < batchnumvertices;j++)
9951                         {
9952                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9953                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9954                         }
9955                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9956                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9957                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9958                         {
9959 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9960 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9961 //                              rsurface.batchsvector3f_bufferoffset = 0;
9962 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9963 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9964 //                              rsurface.batchtvector3f_bufferoffset = 0;
9965                                 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);
9966                         }
9967                         break;
9968                 case Q3DEFORM_MOVE:
9969                         // deform vertex array
9970                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9971                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9972                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9973                         VectorScale(deform->parms, scale, waveparms);
9974 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9975 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9976 //                      rsurface.batchvertex3f_bufferoffset = 0;
9977                         for (j = 0;j < batchnumvertices;j++)
9978                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9979                         break;
9980                 }
9981         }
9982
9983         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9984         {
9985         // generate texcoords based on the chosen texcoord source
9986                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9987                 {
9988                 default:
9989                 case Q3TCGEN_TEXTURE:
9990                         break;
9991                 case Q3TCGEN_LIGHTMAP:
9992         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9993         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9994         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9995                         if (rsurface.batchtexcoordlightmap2f)
9996                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9997                         break;
9998                 case Q3TCGEN_VECTOR:
9999         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10000         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10001         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10002                         for (j = 0;j < batchnumvertices;j++)
10003                         {
10004                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10005                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10006                         }
10007                         break;
10008                 case Q3TCGEN_ENVIRONMENT:
10009                         // make environment reflections using a spheremap
10010                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10011                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10012                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10013                         for (j = 0;j < batchnumvertices;j++)
10014                         {
10015                                 // identical to Q3A's method, but executed in worldspace so
10016                                 // carried models can be shiny too
10017
10018                                 float viewer[3], d, reflected[3], worldreflected[3];
10019
10020                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10021                                 // VectorNormalize(viewer);
10022
10023                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10024
10025                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10026                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10027                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10028                                 // note: this is proportinal to viewer, so we can normalize later
10029
10030                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10031                                 VectorNormalize(worldreflected);
10032
10033                                 // note: this sphere map only uses world x and z!
10034                                 // so positive and negative y will LOOK THE SAME.
10035                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10036                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10037                         }
10038                         break;
10039                 }
10040                 // the only tcmod that needs software vertex processing is turbulent, so
10041                 // check for it here and apply the changes if needed
10042                 // and we only support that as the first one
10043                 // (handling a mixture of turbulent and other tcmods would be problematic
10044                 //  without punting it entirely to a software path)
10045                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10046                 {
10047                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10048                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10049         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10050         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10051         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10052                         for (j = 0;j < batchnumvertices;j++)
10053                         {
10054                                 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);
10055                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10056                         }
10057                 }
10058         }
10059
10060         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10061         {
10062                 // convert the modified arrays to vertex structs
10063 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10064 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10065 //              rsurface.batchvertexmesh_bufferoffset = 0;
10066                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10067                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10068                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10069                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10070                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10071                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10072                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10073                 {
10074                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10075                         {
10076                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10077                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10078                         }
10079                 }
10080                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10081                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10082                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10083                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10084                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10085                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10086                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10087                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10088                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10089                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10090                 {
10091                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10092                         {
10093                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10094                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10095                         }
10096                 }
10097         }
10098
10099         // upload buffer data for the dynamic batch
10100         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10101         {
10102                 if (rsurface.batchvertexmesh)
10103                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10104                 else
10105                 {
10106                         if (rsurface.batchvertex3f)
10107                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10108                         if (rsurface.batchsvector3f)
10109                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10110                         if (rsurface.batchtvector3f)
10111                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10112                         if (rsurface.batchnormal3f)
10113                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10114                         if (rsurface.batchlightmapcolor4f)
10115                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10116                         if (rsurface.batchtexcoordtexture2f)
10117                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10118                         if (rsurface.batchtexcoordlightmap2f)
10119                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10120                         if (rsurface.batchskeletalindex4ub)
10121                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10122                         if (rsurface.batchskeletalweight4ub)
10123                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10124                 }
10125                 if (rsurface.batchelement3s)
10126                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10127                 else if (rsurface.batchelement3i)
10128                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10129         }
10130 }
10131
10132 void RSurf_DrawBatch(void)
10133 {
10134         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10135         // through the pipeline, killing it earlier in the pipeline would have
10136         // per-surface overhead rather than per-batch overhead, so it's best to
10137         // reject it here, before it hits glDraw.
10138         if (rsurface.batchnumtriangles == 0)
10139                 return;
10140 #if 0
10141         // batch debugging code
10142         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10143         {
10144                 int i;
10145                 int j;
10146                 int c;
10147                 const int *e;
10148                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10149                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10150                 {
10151                         c = e[i];
10152                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10153                         {
10154                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10155                                 {
10156                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10157                                                 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);
10158                                         break;
10159                                 }
10160                         }
10161                 }
10162         }
10163 #endif
10164         if (rsurface.batchmultidraw)
10165         {
10166                 // issue multiple draws rather than copying index data
10167                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10168                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10169                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10170                 for (i = 0;i < numsurfaces;)
10171                 {
10172                         // combine consecutive surfaces as one draw
10173                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10174                                 if (surfacelist[j] != surfacelist[k] + 1)
10175                                         break;
10176                         firstvertex = surfacelist[i]->num_firstvertex;
10177                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10178                         firsttriangle = surfacelist[i]->num_firsttriangle;
10179                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10180                         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);
10181                         i = j;
10182                 }
10183         }
10184         else
10185         {
10186                 // there is only one consecutive run of index data (may have been combined)
10187                 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);
10188         }
10189 }
10190
10191 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10192 {
10193         // pick the closest matching water plane
10194         int planeindex, vertexindex, bestplaneindex = -1;
10195         float d, bestd;
10196         vec3_t vert;
10197         const float *v;
10198         r_waterstate_waterplane_t *p;
10199         qboolean prepared = false;
10200         bestd = 0;
10201         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10202         {
10203                 if(p->camera_entity != rsurface.texture->camera_entity)
10204                         continue;
10205                 d = 0;
10206                 if(!prepared)
10207                 {
10208                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10209                         prepared = true;
10210                         if(rsurface.batchnumvertices == 0)
10211                                 break;
10212                 }
10213                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10214                 {
10215                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10216                         d += fabs(PlaneDiff(vert, &p->plane));
10217                 }
10218                 if (bestd > d || bestplaneindex < 0)
10219                 {
10220                         bestd = d;
10221                         bestplaneindex = planeindex;
10222                 }
10223         }
10224         return bestplaneindex;
10225         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10226         // this situation though, as it might be better to render single larger
10227         // batches with useless stuff (backface culled for example) than to
10228         // render multiple smaller batches
10229 }
10230
10231 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10232 {
10233         int i;
10234         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10235         rsurface.passcolor4f_vertexbuffer = 0;
10236         rsurface.passcolor4f_bufferoffset = 0;
10237         for (i = 0;i < rsurface.batchnumvertices;i++)
10238                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10239 }
10240
10241 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10242 {
10243         int i;
10244         float f;
10245         const float *v;
10246         const float *c;
10247         float *c2;
10248         if (rsurface.passcolor4f)
10249         {
10250                 // generate color arrays
10251                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10252                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10253                 rsurface.passcolor4f_vertexbuffer = 0;
10254                 rsurface.passcolor4f_bufferoffset = 0;
10255                 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)
10256                 {
10257                         f = RSurf_FogVertex(v);
10258                         c2[0] = c[0] * f;
10259                         c2[1] = c[1] * f;
10260                         c2[2] = c[2] * f;
10261                         c2[3] = c[3];
10262                 }
10263         }
10264         else
10265         {
10266                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10267                 rsurface.passcolor4f_vertexbuffer = 0;
10268                 rsurface.passcolor4f_bufferoffset = 0;
10269                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10270                 {
10271                         f = RSurf_FogVertex(v);
10272                         c2[0] = f;
10273                         c2[1] = f;
10274                         c2[2] = f;
10275                         c2[3] = 1;
10276                 }
10277         }
10278 }
10279
10280 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10281 {
10282         int i;
10283         float f;
10284         const float *v;
10285         const float *c;
10286         float *c2;
10287         if (!rsurface.passcolor4f)
10288                 return;
10289         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10290         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10291         rsurface.passcolor4f_vertexbuffer = 0;
10292         rsurface.passcolor4f_bufferoffset = 0;
10293         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10294         {
10295                 f = RSurf_FogVertex(v);
10296                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10297                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10298                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10299                 c2[3] = c[3];
10300         }
10301 }
10302
10303 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10304 {
10305         int i;
10306         const float *c;
10307         float *c2;
10308         if (!rsurface.passcolor4f)
10309                 return;
10310         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10311         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10312         rsurface.passcolor4f_vertexbuffer = 0;
10313         rsurface.passcolor4f_bufferoffset = 0;
10314         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10315         {
10316                 c2[0] = c[0] * r;
10317                 c2[1] = c[1] * g;
10318                 c2[2] = c[2] * b;
10319                 c2[3] = c[3] * a;
10320         }
10321 }
10322
10323 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10324 {
10325         int i;
10326         const float *c;
10327         float *c2;
10328         if (!rsurface.passcolor4f)
10329                 return;
10330         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10331         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10332         rsurface.passcolor4f_vertexbuffer = 0;
10333         rsurface.passcolor4f_bufferoffset = 0;
10334         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10335         {
10336                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10337                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10338                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10339                 c2[3] = c[3];
10340         }
10341 }
10342
10343 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10344 {
10345         // TODO: optimize
10346         rsurface.passcolor4f = NULL;
10347         rsurface.passcolor4f_vertexbuffer = 0;
10348         rsurface.passcolor4f_bufferoffset = 0;
10349         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10350         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10351         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10352         GL_Color(r, g, b, a);
10353         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10354         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10355         R_Mesh_TexMatrix(0, NULL);
10356         RSurf_DrawBatch();
10357 }
10358
10359 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10360 {
10361         // TODO: optimize applyfog && applycolor case
10362         // just apply fog if necessary, and tint the fog color array if necessary
10363         rsurface.passcolor4f = NULL;
10364         rsurface.passcolor4f_vertexbuffer = 0;
10365         rsurface.passcolor4f_bufferoffset = 0;
10366         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10367         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10368         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10369         GL_Color(r, g, b, a);
10370         RSurf_DrawBatch();
10371 }
10372
10373 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10374 {
10375         // TODO: optimize
10376         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10377         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10378         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10379         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10380         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10381         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10382         GL_Color(r, g, b, a);
10383         RSurf_DrawBatch();
10384 }
10385
10386 static void RSurf_DrawBatch_GL11_ClampColor(void)
10387 {
10388         int i;
10389         const float *c1;
10390         float *c2;
10391         if (!rsurface.passcolor4f)
10392                 return;
10393         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10394         {
10395                 c2[0] = bound(0.0f, c1[0], 1.0f);
10396                 c2[1] = bound(0.0f, c1[1], 1.0f);
10397                 c2[2] = bound(0.0f, c1[2], 1.0f);
10398                 c2[3] = bound(0.0f, c1[3], 1.0f);
10399         }
10400 }
10401
10402 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10403 {
10404         int i;
10405         float f;
10406         const float *v;
10407         const float *n;
10408         float *c;
10409         //vec3_t eyedir;
10410
10411         // fake shading
10412         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10413         rsurface.passcolor4f_vertexbuffer = 0;
10414         rsurface.passcolor4f_bufferoffset = 0;
10415         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)
10416         {
10417                 f = -DotProduct(r_refdef.view.forward, n);
10418                 f = max(0, f);
10419                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10420                 f *= fakelightintensity;
10421                 Vector4Set(c, f, f, f, 1);
10422         }
10423 }
10424
10425 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10426 {
10427         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10428         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10429         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10430         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10431         GL_Color(r, g, b, a);
10432         RSurf_DrawBatch();
10433 }
10434
10435 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10436 {
10437         int i;
10438         float f;
10439         float alpha;
10440         const float *v;
10441         const float *n;
10442         float *c;
10443         vec3_t ambientcolor;
10444         vec3_t diffusecolor;
10445         vec3_t lightdir;
10446         // TODO: optimize
10447         // model lighting
10448         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10449         f = 0.5f * lightmapintensity;
10450         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10451         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10452         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10453         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10454         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10455         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10456         alpha = *a;
10457         if (VectorLength2(diffusecolor) > 0)
10458         {
10459                 // q3-style directional shading
10460                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10461                 rsurface.passcolor4f_vertexbuffer = 0;
10462                 rsurface.passcolor4f_bufferoffset = 0;
10463                 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)
10464                 {
10465                         if ((f = DotProduct(n, lightdir)) > 0)
10466                                 VectorMA(ambientcolor, f, diffusecolor, c);
10467                         else
10468                                 VectorCopy(ambientcolor, c);
10469                         c[3] = alpha;
10470                 }
10471                 *r = 1;
10472                 *g = 1;
10473                 *b = 1;
10474                 *a = 1;
10475                 *applycolor = false;
10476         }
10477         else
10478         {
10479                 *r = ambientcolor[0];
10480                 *g = ambientcolor[1];
10481                 *b = ambientcolor[2];
10482                 rsurface.passcolor4f = NULL;
10483                 rsurface.passcolor4f_vertexbuffer = 0;
10484                 rsurface.passcolor4f_bufferoffset = 0;
10485         }
10486 }
10487
10488 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10489 {
10490         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10491         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10492         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10493         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10494         GL_Color(r, g, b, a);
10495         RSurf_DrawBatch();
10496 }
10497
10498 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10499 {
10500         int i;
10501         float f;
10502         const float *v;
10503         float *c;
10504
10505         // fake shading
10506         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10507         rsurface.passcolor4f_vertexbuffer = 0;
10508         rsurface.passcolor4f_bufferoffset = 0;
10509
10510         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10511         {
10512                 f = 1 - RSurf_FogVertex(v);
10513                 c[0] = r;
10514                 c[1] = g;
10515                 c[2] = b;
10516                 c[3] = f * a;
10517         }
10518 }
10519
10520 void RSurf_SetupDepthAndCulling(void)
10521 {
10522         // submodels are biased to avoid z-fighting with world surfaces that they
10523         // may be exactly overlapping (avoids z-fighting artifacts on certain
10524         // doors and things in Quake maps)
10525         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10526         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10527         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10528         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10529 }
10530
10531 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10532 {
10533         int i, j;
10534         // transparent sky would be ridiculous
10535         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10536                 return;
10537         R_SetupShader_Generic_NoTexture(false, false);
10538         skyrenderlater = true;
10539         RSurf_SetupDepthAndCulling();
10540         GL_DepthMask(true);
10541
10542         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10543         if (r_sky_scissor.integer)
10544         {
10545                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10546                 for (i = 0; i < texturenumsurfaces; i++)
10547                 {
10548                         const msurface_t *surf = texturesurfacelist[i];
10549                         const float *v;
10550                         float p[3];
10551                         float mins[3], maxs[3];
10552                         int scissor[4];
10553                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10554                         {
10555                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10556                                 if (j > 0)
10557                                 {
10558                                         if (mins[0] > p[0]) mins[0] = p[0];
10559                                         if (mins[1] > p[1]) mins[1] = p[1];
10560                                         if (mins[2] > p[2]) mins[2] = p[2];
10561                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10562                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10563                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10564                                 }
10565                                 else
10566                                 {
10567                                         VectorCopy(p, mins);
10568                                         VectorCopy(p, maxs);
10569                                 }
10570                         }
10571                         if (!R_ScissorForBBox(mins, maxs, scissor))
10572                         {
10573                                 if (skyscissor[2])
10574                                 {
10575                                         if (skyscissor[0] > scissor[0])
10576                                         {
10577                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10578                                                 skyscissor[0] = scissor[0];
10579                                         }
10580                                         if (skyscissor[1] > scissor[1])
10581                                         {
10582                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10583                                                 skyscissor[1] = scissor[1];
10584                                         }
10585                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10586                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10587                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10588                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10589                                 }
10590                                 else
10591                                         Vector4Copy(scissor, skyscissor);
10592                         }
10593                 }
10594         }
10595
10596         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10597         // skymasking on them, and Quake3 never did sky masking (unlike
10598         // software Quake and software Quake2), so disable the sky masking
10599         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10600         // and skymasking also looks very bad when noclipping outside the
10601         // level, so don't use it then either.
10602         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10603         {
10604                 R_Mesh_ResetTextureState();
10605                 if (skyrendermasked)
10606                 {
10607                         R_SetupShader_DepthOrShadow(false, false, false);
10608                         // depth-only (masking)
10609                         GL_ColorMask(0, 0, 0, 0);
10610                         // just to make sure that braindead drivers don't draw
10611                         // anything despite that colormask...
10612                         GL_BlendFunc(GL_ZERO, GL_ONE);
10613                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10614                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10615                 }
10616                 else
10617                 {
10618                         R_SetupShader_Generic_NoTexture(false, false);
10619                         // fog sky
10620                         GL_BlendFunc(GL_ONE, GL_ZERO);
10621                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10622                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10623                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10624                 }
10625                 RSurf_DrawBatch();
10626                 if (skyrendermasked)
10627                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10628         }
10629         R_Mesh_ResetTextureState();
10630         GL_Color(1, 1, 1, 1);
10631 }
10632
10633 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10634 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10635 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10636 {
10637         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10638                 return;
10639         if (prepass)
10640         {
10641                 // render screenspace normalmap to texture
10642                 GL_DepthMask(true);
10643                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10644                 RSurf_DrawBatch();
10645                 return;
10646         }
10647
10648         // bind lightmap texture
10649
10650         // water/refraction/reflection/camera surfaces have to be handled specially
10651         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10652         {
10653                 int start, end, startplaneindex;
10654                 for (start = 0;start < texturenumsurfaces;start = end)
10655                 {
10656                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10657                         if(startplaneindex < 0)
10658                         {
10659                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10660                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10661                                 end = start + 1;
10662                                 continue;
10663                         }
10664                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10665                                 ;
10666                         // now that we have a batch using the same planeindex, render it
10667                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10668                         {
10669                                 // render water or distortion background
10670                                 GL_DepthMask(true);
10671                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10672                                 RSurf_DrawBatch();
10673                                 // blend surface on top
10674                                 GL_DepthMask(false);
10675                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10676                                 RSurf_DrawBatch();
10677                         }
10678                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10679                         {
10680                                 // render surface with reflection texture as input
10681                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10682                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10683                                 RSurf_DrawBatch();
10684                         }
10685                 }
10686                 return;
10687         }
10688
10689         // render surface batch normally
10690         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10691         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10692         RSurf_DrawBatch();
10693 }
10694
10695 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10696 {
10697         // OpenGL 1.3 path - anything not completely ancient
10698         qboolean applycolor;
10699         qboolean applyfog;
10700         int layerindex;
10701         const texturelayer_t *layer;
10702         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);
10703         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10704
10705         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10706         {
10707                 vec4_t layercolor;
10708                 int layertexrgbscale;
10709                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10710                 {
10711                         if (layerindex == 0)
10712                                 GL_AlphaTest(true);
10713                         else
10714                         {
10715                                 GL_AlphaTest(false);
10716                                 GL_DepthFunc(GL_EQUAL);
10717                         }
10718                 }
10719                 GL_DepthMask(layer->depthmask && writedepth);
10720                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10721                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10722                 {
10723                         layertexrgbscale = 4;
10724                         VectorScale(layer->color, 0.25f, layercolor);
10725                 }
10726                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10727                 {
10728                         layertexrgbscale = 2;
10729                         VectorScale(layer->color, 0.5f, layercolor);
10730                 }
10731                 else
10732                 {
10733                         layertexrgbscale = 1;
10734                         VectorScale(layer->color, 1.0f, layercolor);
10735                 }
10736                 layercolor[3] = layer->color[3];
10737                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10738                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10739                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10740                 switch (layer->type)
10741                 {
10742                 case TEXTURELAYERTYPE_LITTEXTURE:
10743                         // single-pass lightmapped texture with 2x rgbscale
10744                         R_Mesh_TexBind(0, r_texture_white);
10745                         R_Mesh_TexMatrix(0, NULL);
10746                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10747                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10748                         R_Mesh_TexBind(1, layer->texture);
10749                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10750                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10751                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10752                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10753                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10754                         else if (FAKELIGHT_ENABLED)
10755                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10756                         else if (rsurface.uselightmaptexture)
10757                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10758                         else
10759                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10760                         break;
10761                 case TEXTURELAYERTYPE_TEXTURE:
10762                         // singletexture unlit texture with transparency support
10763                         R_Mesh_TexBind(0, layer->texture);
10764                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10765                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10766                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10767                         R_Mesh_TexBind(1, 0);
10768                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10769                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10770                         break;
10771                 case TEXTURELAYERTYPE_FOG:
10772                         // singletexture fogging
10773                         if (layer->texture)
10774                         {
10775                                 R_Mesh_TexBind(0, layer->texture);
10776                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10777                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10778                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10779                         }
10780                         else
10781                         {
10782                                 R_Mesh_TexBind(0, 0);
10783                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10784                         }
10785                         R_Mesh_TexBind(1, 0);
10786                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10787                         // generate a color array for the fog pass
10788                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10789                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10790                         RSurf_DrawBatch();
10791                         break;
10792                 default:
10793                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10794                 }
10795         }
10796         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10797         {
10798                 GL_DepthFunc(GL_LEQUAL);
10799                 GL_AlphaTest(false);
10800         }
10801 }
10802
10803 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10804 {
10805         // OpenGL 1.1 - crusty old voodoo path
10806         qboolean applyfog;
10807         int layerindex;
10808         const texturelayer_t *layer;
10809         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);
10810         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10811
10812         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10813         {
10814                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10815                 {
10816                         if (layerindex == 0)
10817                                 GL_AlphaTest(true);
10818                         else
10819                         {
10820                                 GL_AlphaTest(false);
10821                                 GL_DepthFunc(GL_EQUAL);
10822                         }
10823                 }
10824                 GL_DepthMask(layer->depthmask && writedepth);
10825                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10826                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10827                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10828                 switch (layer->type)
10829                 {
10830                 case TEXTURELAYERTYPE_LITTEXTURE:
10831                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10832                         {
10833                                 // two-pass lit texture with 2x rgbscale
10834                                 // first the lightmap pass
10835                                 R_Mesh_TexBind(0, r_texture_white);
10836                                 R_Mesh_TexMatrix(0, NULL);
10837                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10838                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10839                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10840                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10841                                 else if (FAKELIGHT_ENABLED)
10842                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10843                                 else if (rsurface.uselightmaptexture)
10844                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10845                                 else
10846                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10847                                 // then apply the texture to it
10848                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10849                                 R_Mesh_TexBind(0, layer->texture);
10850                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10851                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10852                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10853                                 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);
10854                         }
10855                         else
10856                         {
10857                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10858                                 R_Mesh_TexBind(0, layer->texture);
10859                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10860                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10861                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10862                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10863                                         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);
10864                                 else if (FAKELIGHT_ENABLED)
10865                                         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);
10866                                 else
10867                                         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);
10868                         }
10869                         break;
10870                 case TEXTURELAYERTYPE_TEXTURE:
10871                         // singletexture unlit texture with transparency support
10872                         R_Mesh_TexBind(0, layer->texture);
10873                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10874                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10875                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10876                         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);
10877                         break;
10878                 case TEXTURELAYERTYPE_FOG:
10879                         // singletexture fogging
10880                         if (layer->texture)
10881                         {
10882                                 R_Mesh_TexBind(0, layer->texture);
10883                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10884                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10885                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10886                         }
10887                         else
10888                         {
10889                                 R_Mesh_TexBind(0, 0);
10890                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10891                         }
10892                         // generate a color array for the fog pass
10893                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10894                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10895                         RSurf_DrawBatch();
10896                         break;
10897                 default:
10898                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10899                 }
10900         }
10901         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10902         {
10903                 GL_DepthFunc(GL_LEQUAL);
10904                 GL_AlphaTest(false);
10905         }
10906 }
10907
10908 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10909 {
10910         int vi;
10911         int j;
10912         r_vertexgeneric_t *batchvertex;
10913         float c[4];
10914         texture_t *t = rsurface.texture;
10915
10916 //      R_Mesh_ResetTextureState();
10917         R_SetupShader_Generic_NoTexture(false, false);
10918
10919         if(t && t->currentskinframe)
10920         {
10921                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10922                 c[3] *= t->currentalpha;
10923         }
10924         else
10925         {
10926                 c[0] = 1;
10927                 c[1] = 0;
10928                 c[2] = 1;
10929                 c[3] = 1;
10930         }
10931
10932         if (t->pantstexture || t->shirttexture)
10933         {
10934                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10935                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10936                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10937         }
10938
10939         // brighten it up (as texture value 127 means "unlit")
10940         c[0] *= 2 * r_refdef.view.colorscale;
10941         c[1] *= 2 * r_refdef.view.colorscale;
10942         c[2] *= 2 * r_refdef.view.colorscale;
10943
10944         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10945                 c[3] *= r_wateralpha.value;
10946
10947         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10948         {
10949                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10950                 GL_DepthMask(false);
10951         }
10952         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10953         {
10954                 GL_BlendFunc(GL_ONE, GL_ONE);
10955                 GL_DepthMask(false);
10956         }
10957         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10958         {
10959                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10960                 GL_DepthMask(false);
10961         }
10962         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10963         {
10964                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10965                 GL_DepthMask(false);
10966         }
10967         else
10968         {
10969                 GL_BlendFunc(GL_ONE, GL_ZERO);
10970                 GL_DepthMask(writedepth);
10971         }
10972
10973         if (r_showsurfaces.integer == 3)
10974         {
10975                 rsurface.passcolor4f = NULL;
10976
10977                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10978                 {
10979                         qboolean applycolor = true;
10980                         float one = 1.0;
10981
10982                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10983
10984                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10985                 }
10986                 else if (FAKELIGHT_ENABLED)
10987                 {
10988                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10989
10990                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10991                 }
10992                 else
10993                 {
10994                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10995
10996                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10997                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10998                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10999                         RSurf_DrawBatch_GL11_ApplyAmbient();
11000                 }
11001
11002                 if(!rsurface.passcolor4f)
11003                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11004
11005                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11006                 if(r_refdef.fogenabled)
11007                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11008                 RSurf_DrawBatch_GL11_ClampColor();
11009
11010                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11011                 R_SetupShader_Generic_NoTexture(false, false);
11012                 RSurf_DrawBatch();
11013         }
11014         else if (!r_refdef.view.showdebug)
11015         {
11016                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11017                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11018                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11019                 {
11020                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11021                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11022                 }
11023                 R_Mesh_PrepareVertices_Generic_Unlock();
11024                 RSurf_DrawBatch();
11025         }
11026         else if (r_showsurfaces.integer == 4)
11027         {
11028                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11029                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11030                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11031                 {
11032                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11033                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11034                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11035                 }
11036                 R_Mesh_PrepareVertices_Generic_Unlock();
11037                 RSurf_DrawBatch();
11038         }
11039         else if (r_showsurfaces.integer == 2)
11040         {
11041                 const int *e;
11042                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11043                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11044                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11045                 {
11046                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11047                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11048                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11049                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11050                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11051                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11052                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11053                 }
11054                 R_Mesh_PrepareVertices_Generic_Unlock();
11055                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11056         }
11057         else
11058         {
11059                 int texturesurfaceindex;
11060                 int k;
11061                 const msurface_t *surface;
11062                 float surfacecolor4f[4];
11063                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11065                 vi = 0;
11066                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11067                 {
11068                         surface = texturesurfacelist[texturesurfaceindex];
11069                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11070                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11071                         for (j = 0;j < surface->num_vertices;j++)
11072                         {
11073                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11074                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11075                                 vi++;
11076                         }
11077                 }
11078                 R_Mesh_PrepareVertices_Generic_Unlock();
11079                 RSurf_DrawBatch();
11080         }
11081 }
11082
11083 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11084 {
11085         CHECKGLERROR
11086         RSurf_SetupDepthAndCulling();
11087         if (r_showsurfaces.integer)
11088         {
11089                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11090                 return;
11091         }
11092         switch (vid.renderpath)
11093         {
11094         case RENDERPATH_GL20:
11095         case RENDERPATH_D3D9:
11096         case RENDERPATH_D3D10:
11097         case RENDERPATH_D3D11:
11098         case RENDERPATH_SOFT:
11099         case RENDERPATH_GLES2:
11100                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11101                 break;
11102         case RENDERPATH_GL13:
11103         case RENDERPATH_GLES1:
11104                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11105                 break;
11106         case RENDERPATH_GL11:
11107                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11108                 break;
11109         }
11110         CHECKGLERROR
11111 }
11112
11113 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11114 {
11115         int i, j;
11116         int texturenumsurfaces, endsurface;
11117         texture_t *texture;
11118         const msurface_t *surface;
11119         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11120
11121         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11122                 RSurf_ActiveModelEntity(ent, false, false, false);
11123         else
11124         {
11125                 switch (vid.renderpath)
11126                 {
11127                 case RENDERPATH_GL20:
11128                 case RENDERPATH_D3D9:
11129                 case RENDERPATH_D3D10:
11130                 case RENDERPATH_D3D11:
11131                 case RENDERPATH_SOFT:
11132                 case RENDERPATH_GLES2:
11133                         RSurf_ActiveModelEntity(ent, true, true, false);
11134                         break;
11135                 case RENDERPATH_GL11:
11136                 case RENDERPATH_GL13:
11137                 case RENDERPATH_GLES1:
11138                         RSurf_ActiveModelEntity(ent, true, false, false);
11139                         break;
11140                 }
11141         }
11142
11143         if (r_transparentdepthmasking.integer)
11144         {
11145                 qboolean setup = false;
11146                 for (i = 0;i < numsurfaces;i = j)
11147                 {
11148                         j = i + 1;
11149                         surface = rsurface.modelsurfaces + surfacelist[i];
11150                         texture = surface->texture;
11151                         rsurface.texture = R_GetCurrentTexture(texture);
11152                         rsurface.lightmaptexture = NULL;
11153                         rsurface.deluxemaptexture = NULL;
11154                         rsurface.uselightmaptexture = false;
11155                         // scan ahead until we find a different texture
11156                         endsurface = min(i + 1024, numsurfaces);
11157                         texturenumsurfaces = 0;
11158                         texturesurfacelist[texturenumsurfaces++] = surface;
11159                         for (;j < endsurface;j++)
11160                         {
11161                                 surface = rsurface.modelsurfaces + surfacelist[j];
11162                                 if (texture != surface->texture)
11163                                         break;
11164                                 texturesurfacelist[texturenumsurfaces++] = surface;
11165                         }
11166                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11167                                 continue;
11168                         // render the range of surfaces as depth
11169                         if (!setup)
11170                         {
11171                                 setup = true;
11172                                 GL_ColorMask(0,0,0,0);
11173                                 GL_Color(1,1,1,1);
11174                                 GL_DepthTest(true);
11175                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11176                                 GL_DepthMask(true);
11177 //                              R_Mesh_ResetTextureState();
11178                         }
11179                         RSurf_SetupDepthAndCulling();
11180                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11181                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11182                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11183                         RSurf_DrawBatch();
11184                 }
11185                 if (setup)
11186                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11187         }
11188
11189         for (i = 0;i < numsurfaces;i = j)
11190         {
11191                 j = i + 1;
11192                 surface = rsurface.modelsurfaces + surfacelist[i];
11193                 texture = surface->texture;
11194                 rsurface.texture = R_GetCurrentTexture(texture);
11195                 // scan ahead until we find a different texture
11196                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11197                 texturenumsurfaces = 0;
11198                 texturesurfacelist[texturenumsurfaces++] = surface;
11199                 if(FAKELIGHT_ENABLED)
11200                 {
11201                         rsurface.lightmaptexture = NULL;
11202                         rsurface.deluxemaptexture = NULL;
11203                         rsurface.uselightmaptexture = false;
11204                         for (;j < endsurface;j++)
11205                         {
11206                                 surface = rsurface.modelsurfaces + surfacelist[j];
11207                                 if (texture != surface->texture)
11208                                         break;
11209                                 texturesurfacelist[texturenumsurfaces++] = surface;
11210                         }
11211                 }
11212                 else
11213                 {
11214                         rsurface.lightmaptexture = surface->lightmaptexture;
11215                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11216                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11217                         for (;j < endsurface;j++)
11218                         {
11219                                 surface = rsurface.modelsurfaces + surfacelist[j];
11220                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11221                                         break;
11222                                 texturesurfacelist[texturenumsurfaces++] = surface;
11223                         }
11224                 }
11225                 // render the range of surfaces
11226                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11227         }
11228         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11229 }
11230
11231 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11232 {
11233         // transparent surfaces get pushed off into the transparent queue
11234         int surfacelistindex;
11235         const msurface_t *surface;
11236         vec3_t tempcenter, center;
11237         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11238         {
11239                 surface = texturesurfacelist[surfacelistindex];
11240                 if (r_transparent_sortsurfacesbynearest.integer)
11241                 {
11242                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11243                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11244                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11245                 }
11246                 else
11247                 {
11248                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11249                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11250                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11251                 }
11252                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11253                 if (rsurface.entity->transparent_offset) // transparent offset
11254                 {
11255                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11256                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11257                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11258                 }
11259                 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);
11260         }
11261 }
11262
11263 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11264 {
11265         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11266                 return;
11267         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11268                 return;
11269         RSurf_SetupDepthAndCulling();
11270         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11271         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11272         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11273         RSurf_DrawBatch();
11274 }
11275
11276 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11277 {
11278         CHECKGLERROR
11279         if (depthonly)
11280                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11281         else if (prepass)
11282         {
11283                 if (!rsurface.texture->currentnumlayers)
11284                         return;
11285                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11286                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11287                 else
11288                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11289         }
11290         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11291                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11292         else if (!rsurface.texture->currentnumlayers)
11293                 return;
11294         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11295         {
11296                 // in the deferred case, transparent surfaces were queued during prepass
11297                 if (!r_shadow_usingdeferredprepass)
11298                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11299         }
11300         else
11301         {
11302                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11303                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11304         }
11305         CHECKGLERROR
11306 }
11307
11308 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11309 {
11310         int i, j;
11311         texture_t *texture;
11312         R_FrameData_SetMark();
11313         // break the surface list down into batches by texture and use of lightmapping
11314         for (i = 0;i < numsurfaces;i = j)
11315         {
11316                 j = i + 1;
11317                 // texture is the base texture pointer, rsurface.texture is the
11318                 // current frame/skin the texture is directing us to use (for example
11319                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11320                 // use skin 1 instead)
11321                 texture = surfacelist[i]->texture;
11322                 rsurface.texture = R_GetCurrentTexture(texture);
11323                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11324                 {
11325                         // if this texture is not the kind we want, skip ahead to the next one
11326                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11327                                 ;
11328                         continue;
11329                 }
11330                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11331                 {
11332                         rsurface.lightmaptexture = NULL;
11333                         rsurface.deluxemaptexture = NULL;
11334                         rsurface.uselightmaptexture = false;
11335                         // simply scan ahead until we find a different texture or lightmap state
11336                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11337                                 ;
11338                 }
11339                 else
11340                 {
11341                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11342                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11343                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11344                         // simply scan ahead until we find a different texture or lightmap state
11345                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11346                                 ;
11347                 }
11348                 // render the range of surfaces
11349                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11350         }
11351         R_FrameData_ReturnToMark();
11352 }
11353
11354 float locboxvertex3f[6*4*3] =
11355 {
11356         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11357         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11358         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11359         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11360         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11361         1,0,0, 0,0,0, 0,1,0, 1,1,0
11362 };
11363
11364 unsigned short locboxelements[6*2*3] =
11365 {
11366          0, 1, 2, 0, 2, 3,
11367          4, 5, 6, 4, 6, 7,
11368          8, 9,10, 8,10,11,
11369         12,13,14, 12,14,15,
11370         16,17,18, 16,18,19,
11371         20,21,22, 20,22,23
11372 };
11373
11374 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11375 {
11376         int i, j;
11377         cl_locnode_t *loc = (cl_locnode_t *)ent;
11378         vec3_t mins, size;
11379         float vertex3f[6*4*3];
11380         CHECKGLERROR
11381         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11382         GL_DepthMask(false);
11383         GL_DepthRange(0, 1);
11384         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11385         GL_DepthTest(true);
11386         GL_CullFace(GL_NONE);
11387         R_EntityMatrix(&identitymatrix);
11388
11389 //      R_Mesh_ResetTextureState();
11390
11391         i = surfacelist[0];
11392         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11393                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11394                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11395                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11396
11397         if (VectorCompare(loc->mins, loc->maxs))
11398         {
11399                 VectorSet(size, 2, 2, 2);
11400                 VectorMA(loc->mins, -0.5f, size, mins);
11401         }
11402         else
11403         {
11404                 VectorCopy(loc->mins, mins);
11405                 VectorSubtract(loc->maxs, loc->mins, size);
11406         }
11407
11408         for (i = 0;i < 6*4*3;)
11409                 for (j = 0;j < 3;j++, i++)
11410                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11411
11412         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11413         R_SetupShader_Generic_NoTexture(false, false);
11414         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11415 }
11416
11417 void R_DrawLocs(void)
11418 {
11419         int index;
11420         cl_locnode_t *loc, *nearestloc;
11421         vec3_t center;
11422         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11423         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11424         {
11425                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11426                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11427         }
11428 }
11429
11430 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11431 {
11432         if (decalsystem->decals)
11433                 Mem_Free(decalsystem->decals);
11434         memset(decalsystem, 0, sizeof(*decalsystem));
11435 }
11436
11437 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)
11438 {
11439         tridecal_t *decal;
11440         tridecal_t *decals;
11441         int i;
11442
11443         // expand or initialize the system
11444         if (decalsystem->maxdecals <= decalsystem->numdecals)
11445         {
11446                 decalsystem_t old = *decalsystem;
11447                 qboolean useshortelements;
11448                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11449                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11450                 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)));
11451                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11452                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11453                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11454                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11455                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11456                 if (decalsystem->numdecals)
11457                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11458                 if (old.decals)
11459                         Mem_Free(old.decals);
11460                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11461                         decalsystem->element3i[i] = i;
11462                 if (useshortelements)
11463                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11464                                 decalsystem->element3s[i] = i;
11465         }
11466
11467         // grab a decal and search for another free slot for the next one
11468         decals = decalsystem->decals;
11469         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11470         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11471                 ;
11472         decalsystem->freedecal = i;
11473         if (decalsystem->numdecals <= i)
11474                 decalsystem->numdecals = i + 1;
11475
11476         // initialize the decal
11477         decal->lived = 0;
11478         decal->triangleindex = triangleindex;
11479         decal->surfaceindex = surfaceindex;
11480         decal->decalsequence = decalsequence;
11481         decal->color4f[0][0] = c0[0];
11482         decal->color4f[0][1] = c0[1];
11483         decal->color4f[0][2] = c0[2];
11484         decal->color4f[0][3] = 1;
11485         decal->color4f[1][0] = c1[0];
11486         decal->color4f[1][1] = c1[1];
11487         decal->color4f[1][2] = c1[2];
11488         decal->color4f[1][3] = 1;
11489         decal->color4f[2][0] = c2[0];
11490         decal->color4f[2][1] = c2[1];
11491         decal->color4f[2][2] = c2[2];
11492         decal->color4f[2][3] = 1;
11493         decal->vertex3f[0][0] = v0[0];
11494         decal->vertex3f[0][1] = v0[1];
11495         decal->vertex3f[0][2] = v0[2];
11496         decal->vertex3f[1][0] = v1[0];
11497         decal->vertex3f[1][1] = v1[1];
11498         decal->vertex3f[1][2] = v1[2];
11499         decal->vertex3f[2][0] = v2[0];
11500         decal->vertex3f[2][1] = v2[1];
11501         decal->vertex3f[2][2] = v2[2];
11502         decal->texcoord2f[0][0] = t0[0];
11503         decal->texcoord2f[0][1] = t0[1];
11504         decal->texcoord2f[1][0] = t1[0];
11505         decal->texcoord2f[1][1] = t1[1];
11506         decal->texcoord2f[2][0] = t2[0];
11507         decal->texcoord2f[2][1] = t2[1];
11508         TriangleNormal(v0, v1, v2, decal->plane);
11509         VectorNormalize(decal->plane);
11510         decal->plane[3] = DotProduct(v0, decal->plane);
11511 }
11512
11513 extern cvar_t cl_decals_bias;
11514 extern cvar_t cl_decals_models;
11515 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11516 // baseparms, parms, temps
11517 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)
11518 {
11519         int cornerindex;
11520         int index;
11521         float v[9][3];
11522         const float *vertex3f;
11523         const float *normal3f;
11524         int numpoints;
11525         float points[2][9][3];
11526         float temp[3];
11527         float tc[9][2];
11528         float f;
11529         float c[9][4];
11530         const int *e;
11531
11532         e = rsurface.modelelement3i + 3*triangleindex;
11533
11534         vertex3f = rsurface.modelvertex3f;
11535         normal3f = rsurface.modelnormal3f;
11536
11537         if (normal3f)
11538         {
11539                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11540                 {
11541                         index = 3*e[cornerindex];
11542                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11543                 }
11544         }
11545         else
11546         {
11547                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11548                 {
11549                         index = 3*e[cornerindex];
11550                         VectorCopy(vertex3f + index, v[cornerindex]);
11551                 }
11552         }
11553
11554         // cull backfaces
11555         //TriangleNormal(v[0], v[1], v[2], normal);
11556         //if (DotProduct(normal, localnormal) < 0.0f)
11557         //      continue;
11558         // clip by each of the box planes formed from the projection matrix
11559         // if anything survives, we emit the decal
11560         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]);
11561         if (numpoints < 3)
11562                 return;
11563         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]);
11564         if (numpoints < 3)
11565                 return;
11566         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]);
11567         if (numpoints < 3)
11568                 return;
11569         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]);
11570         if (numpoints < 3)
11571                 return;
11572         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]);
11573         if (numpoints < 3)
11574                 return;
11575         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]);
11576         if (numpoints < 3)
11577                 return;
11578         // some part of the triangle survived, so we have to accept it...
11579         if (dynamic)
11580         {
11581                 // dynamic always uses the original triangle
11582                 numpoints = 3;
11583                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11584                 {
11585                         index = 3*e[cornerindex];
11586                         VectorCopy(vertex3f + index, v[cornerindex]);
11587                 }
11588         }
11589         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11590         {
11591                 // convert vertex positions to texcoords
11592                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11593                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11594                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11595                 // calculate distance fade from the projection origin
11596                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11597                 f = bound(0.0f, f, 1.0f);
11598                 c[cornerindex][0] = r * f;
11599                 c[cornerindex][1] = g * f;
11600                 c[cornerindex][2] = b * f;
11601                 c[cornerindex][3] = 1.0f;
11602                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11603         }
11604         if (dynamic)
11605                 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);
11606         else
11607                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11608                         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);
11609 }
11610 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)
11611 {
11612         matrix4x4_t projection;
11613         decalsystem_t *decalsystem;
11614         qboolean dynamic;
11615         dp_model_t *model;
11616         const msurface_t *surface;
11617         const msurface_t *surfaces;
11618         const int *surfacelist;
11619         const texture_t *texture;
11620         int numtriangles;
11621         int numsurfacelist;
11622         int surfacelistindex;
11623         int surfaceindex;
11624         int triangleindex;
11625         float localorigin[3];
11626         float localnormal[3];
11627         float localmins[3];
11628         float localmaxs[3];
11629         float localsize;
11630         //float normal[3];
11631         float planes[6][4];
11632         float angles[3];
11633         bih_t *bih;
11634         int bih_triangles_count;
11635         int bih_triangles[256];
11636         int bih_surfaces[256];
11637
11638         decalsystem = &ent->decalsystem;
11639         model = ent->model;
11640         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11641         {
11642                 R_DecalSystem_Reset(&ent->decalsystem);
11643                 return;
11644         }
11645
11646         if (!model->brush.data_leafs && !cl_decals_models.integer)
11647         {
11648                 if (decalsystem->model)
11649                         R_DecalSystem_Reset(decalsystem);
11650                 return;
11651         }
11652
11653         if (decalsystem->model != model)
11654                 R_DecalSystem_Reset(decalsystem);
11655         decalsystem->model = model;
11656
11657         RSurf_ActiveModelEntity(ent, true, false, false);
11658
11659         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11660         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11661         VectorNormalize(localnormal);
11662         localsize = worldsize*rsurface.inversematrixscale;
11663         localmins[0] = localorigin[0] - localsize;
11664         localmins[1] = localorigin[1] - localsize;
11665         localmins[2] = localorigin[2] - localsize;
11666         localmaxs[0] = localorigin[0] + localsize;
11667         localmaxs[1] = localorigin[1] + localsize;
11668         localmaxs[2] = localorigin[2] + localsize;
11669
11670         //VectorCopy(localnormal, planes[4]);
11671         //VectorVectors(planes[4], planes[2], planes[0]);
11672         AnglesFromVectors(angles, localnormal, NULL, false);
11673         AngleVectors(angles, planes[0], planes[2], planes[4]);
11674         VectorNegate(planes[0], planes[1]);
11675         VectorNegate(planes[2], planes[3]);
11676         VectorNegate(planes[4], planes[5]);
11677         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11678         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11679         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11680         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11681         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11682         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11683
11684 #if 1
11685 // works
11686 {
11687         matrix4x4_t forwardprojection;
11688         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11689         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11690 }
11691 #else
11692 // broken
11693 {
11694         float projectionvector[4][3];
11695         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11696         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11697         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11698         projectionvector[0][0] = planes[0][0] * ilocalsize;
11699         projectionvector[0][1] = planes[1][0] * ilocalsize;
11700         projectionvector[0][2] = planes[2][0] * ilocalsize;
11701         projectionvector[1][0] = planes[0][1] * ilocalsize;
11702         projectionvector[1][1] = planes[1][1] * ilocalsize;
11703         projectionvector[1][2] = planes[2][1] * ilocalsize;
11704         projectionvector[2][0] = planes[0][2] * ilocalsize;
11705         projectionvector[2][1] = planes[1][2] * ilocalsize;
11706         projectionvector[2][2] = planes[2][2] * ilocalsize;
11707         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11708         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11709         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11710         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11711 }
11712 #endif
11713
11714         dynamic = model->surfmesh.isanimated;
11715         numsurfacelist = model->nummodelsurfaces;
11716         surfacelist = model->sortedmodelsurfaces;
11717         surfaces = model->data_surfaces;
11718
11719         bih = NULL;
11720         bih_triangles_count = -1;
11721         if(!dynamic)
11722         {
11723                 if(model->render_bih.numleafs)
11724                         bih = &model->render_bih;
11725                 else if(model->collision_bih.numleafs)
11726                         bih = &model->collision_bih;
11727         }
11728         if(bih)
11729                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11730         if(bih_triangles_count == 0)
11731                 return;
11732         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11733                 return;
11734         if(bih_triangles_count > 0)
11735         {
11736                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11737                 {
11738                         surfaceindex = bih_surfaces[triangleindex];
11739                         surface = surfaces + surfaceindex;
11740                         texture = surface->texture;
11741                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11742                                 continue;
11743                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11744                                 continue;
11745                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11746                 }
11747         }
11748         else
11749         {
11750                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11751                 {
11752                         surfaceindex = surfacelist[surfacelistindex];
11753                         surface = surfaces + surfaceindex;
11754                         // check cull box first because it rejects more than any other check
11755                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11756                                 continue;
11757                         // skip transparent surfaces
11758                         texture = surface->texture;
11759                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11760                                 continue;
11761                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11762                                 continue;
11763                         numtriangles = surface->num_triangles;
11764                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11765                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11766                 }
11767         }
11768 }
11769
11770 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11771 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)
11772 {
11773         int renderentityindex;
11774         float worldmins[3];
11775         float worldmaxs[3];
11776         entity_render_t *ent;
11777
11778         if (!cl_decals_newsystem.integer)
11779                 return;
11780
11781         worldmins[0] = worldorigin[0] - worldsize;
11782         worldmins[1] = worldorigin[1] - worldsize;
11783         worldmins[2] = worldorigin[2] - worldsize;
11784         worldmaxs[0] = worldorigin[0] + worldsize;
11785         worldmaxs[1] = worldorigin[1] + worldsize;
11786         worldmaxs[2] = worldorigin[2] + worldsize;
11787
11788         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11789
11790         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11791         {
11792                 ent = r_refdef.scene.entities[renderentityindex];
11793                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11794                         continue;
11795
11796                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11797         }
11798 }
11799
11800 typedef struct r_decalsystem_splatqueue_s
11801 {
11802         vec3_t worldorigin;
11803         vec3_t worldnormal;
11804         float color[4];
11805         float tcrange[4];
11806         float worldsize;
11807         unsigned int decalsequence;
11808 }
11809 r_decalsystem_splatqueue_t;
11810
11811 int r_decalsystem_numqueued = 0;
11812 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11813
11814 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)
11815 {
11816         r_decalsystem_splatqueue_t *queue;
11817
11818         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11819                 return;
11820
11821         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11822         VectorCopy(worldorigin, queue->worldorigin);
11823         VectorCopy(worldnormal, queue->worldnormal);
11824         Vector4Set(queue->color, r, g, b, a);
11825         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11826         queue->worldsize = worldsize;
11827         queue->decalsequence = cl.decalsequence++;
11828 }
11829
11830 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11831 {
11832         int i;
11833         r_decalsystem_splatqueue_t *queue;
11834
11835         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11836                 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);
11837         r_decalsystem_numqueued = 0;
11838 }
11839
11840 extern cvar_t cl_decals_max;
11841 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11842 {
11843         int i;
11844         decalsystem_t *decalsystem = &ent->decalsystem;
11845         int numdecals;
11846         unsigned int killsequence;
11847         tridecal_t *decal;
11848         float frametime;
11849         float lifetime;
11850
11851         if (!decalsystem->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         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11864         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11865
11866         if (decalsystem->lastupdatetime)
11867                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11868         else
11869                 frametime = 0;
11870         decalsystem->lastupdatetime = r_refdef.scene.time;
11871         numdecals = decalsystem->numdecals;
11872
11873         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11874         {
11875                 if (decal->color4f[0][3])
11876                 {
11877                         decal->lived += frametime;
11878                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11879                         {
11880                                 memset(decal, 0, sizeof(*decal));
11881                                 if (decalsystem->freedecal > i)
11882                                         decalsystem->freedecal = i;
11883                         }
11884                 }
11885         }
11886         decal = decalsystem->decals;
11887         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11888                 numdecals--;
11889
11890         // collapse the array by shuffling the tail decals into the gaps
11891         for (;;)
11892         {
11893                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11894                         decalsystem->freedecal++;
11895                 if (decalsystem->freedecal == numdecals)
11896                         break;
11897                 decal[decalsystem->freedecal] = decal[--numdecals];
11898         }
11899
11900         decalsystem->numdecals = numdecals;
11901
11902         if (numdecals <= 0)
11903         {
11904                 // if there are no decals left, reset decalsystem
11905                 R_DecalSystem_Reset(decalsystem);
11906         }
11907 }
11908
11909 extern skinframe_t *decalskinframe;
11910 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11911 {
11912         int i;
11913         decalsystem_t *decalsystem = &ent->decalsystem;
11914         int numdecals;
11915         tridecal_t *decal;
11916         float faderate;
11917         float alpha;
11918         float *v3f;
11919         float *c4f;
11920         float *t2f;
11921         const int *e;
11922         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11923         int numtris = 0;
11924
11925         numdecals = decalsystem->numdecals;
11926         if (!numdecals)
11927                 return;
11928
11929         if (r_showsurfaces.integer)
11930                 return;
11931
11932         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11933         {
11934                 R_DecalSystem_Reset(decalsystem);
11935                 return;
11936         }
11937
11938         // if the model is static it doesn't matter what value we give for
11939         // wantnormals and wanttangents, so this logic uses only rules applicable
11940         // to a model, knowing that they are meaningless otherwise
11941         RSurf_ActiveModelEntity(ent, false, false, false);
11942
11943         decalsystem->lastupdatetime = r_refdef.scene.time;
11944
11945         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11946
11947         // update vertex positions for animated models
11948         v3f = decalsystem->vertex3f;
11949         c4f = decalsystem->color4f;
11950         t2f = decalsystem->texcoord2f;
11951         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11952         {
11953                 if (!decal->color4f[0][3])
11954                         continue;
11955
11956                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11957                         continue;
11958
11959                 // skip backfaces
11960                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11961                         continue;
11962
11963                 // update color values for fading decals
11964                 if (decal->lived >= cl_decals_time.value)
11965                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11966                 else
11967                         alpha = 1.0f;
11968
11969                 c4f[ 0] = decal->color4f[0][0] * alpha;
11970                 c4f[ 1] = decal->color4f[0][1] * alpha;
11971                 c4f[ 2] = decal->color4f[0][2] * alpha;
11972                 c4f[ 3] = 1;
11973                 c4f[ 4] = decal->color4f[1][0] * alpha;
11974                 c4f[ 5] = decal->color4f[1][1] * alpha;
11975                 c4f[ 6] = decal->color4f[1][2] * alpha;
11976                 c4f[ 7] = 1;
11977                 c4f[ 8] = decal->color4f[2][0] * alpha;
11978                 c4f[ 9] = decal->color4f[2][1] * alpha;
11979                 c4f[10] = decal->color4f[2][2] * alpha;
11980                 c4f[11] = 1;
11981
11982                 t2f[0] = decal->texcoord2f[0][0];
11983                 t2f[1] = decal->texcoord2f[0][1];
11984                 t2f[2] = decal->texcoord2f[1][0];
11985                 t2f[3] = decal->texcoord2f[1][1];
11986                 t2f[4] = decal->texcoord2f[2][0];
11987                 t2f[5] = decal->texcoord2f[2][1];
11988
11989                 // update vertex positions for animated models
11990                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11991                 {
11992                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11993                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11994                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11995                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11996                 }
11997                 else
11998                 {
11999                         VectorCopy(decal->vertex3f[0], v3f);
12000                         VectorCopy(decal->vertex3f[1], v3f + 3);
12001                         VectorCopy(decal->vertex3f[2], v3f + 6);
12002                 }
12003
12004                 if (r_refdef.fogenabled)
12005                 {
12006                         alpha = RSurf_FogVertex(v3f);
12007                         VectorScale(c4f, alpha, c4f);
12008                         alpha = RSurf_FogVertex(v3f + 3);
12009                         VectorScale(c4f + 4, alpha, c4f + 4);
12010                         alpha = RSurf_FogVertex(v3f + 6);
12011                         VectorScale(c4f + 8, alpha, c4f + 8);
12012                 }
12013
12014                 v3f += 9;
12015                 c4f += 12;
12016                 t2f += 6;
12017                 numtris++;
12018         }
12019
12020         if (numtris > 0)
12021         {
12022                 r_refdef.stats[r_stat_drawndecals] += numtris;
12023
12024                 // now render the decals all at once
12025                 // (this assumes they all use one particle font texture!)
12026                 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);
12027 //              R_Mesh_ResetTextureState();
12028                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12029                 GL_DepthMask(false);
12030                 GL_DepthRange(0, 1);
12031                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12032                 GL_DepthTest(true);
12033                 GL_CullFace(GL_NONE);
12034                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12035                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12036                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12037         }
12038 }
12039
12040 static void R_DrawModelDecals(void)
12041 {
12042         int i, numdecals;
12043
12044         // fade faster when there are too many decals
12045         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12046         for (i = 0;i < r_refdef.scene.numentities;i++)
12047                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12048
12049         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12050         for (i = 0;i < r_refdef.scene.numentities;i++)
12051                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12052                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12053
12054         R_DecalSystem_ApplySplatEntitiesQueue();
12055
12056         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12057         for (i = 0;i < r_refdef.scene.numentities;i++)
12058                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12059
12060         r_refdef.stats[r_stat_totaldecals] += numdecals;
12061
12062         if (r_showsurfaces.integer)
12063                 return;
12064
12065         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12066
12067         for (i = 0;i < r_refdef.scene.numentities;i++)
12068         {
12069                 if (!r_refdef.viewcache.entityvisible[i])
12070                         continue;
12071                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12072                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12073         }
12074 }
12075
12076 extern cvar_t mod_collision_bih;
12077 static void R_DrawDebugModel(void)
12078 {
12079         entity_render_t *ent = rsurface.entity;
12080         int i, j, flagsmask;
12081         const msurface_t *surface;
12082         dp_model_t *model = ent->model;
12083
12084         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12085                 return;
12086
12087         if (r_showoverdraw.value > 0)
12088         {
12089                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12090                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12091                 R_SetupShader_Generic_NoTexture(false, false);
12092                 GL_DepthTest(false);
12093                 GL_DepthMask(false);
12094                 GL_DepthRange(0, 1);
12095                 GL_BlendFunc(GL_ONE, GL_ONE);
12096                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12097                 {
12098                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12099                                 continue;
12100                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12101                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12102                         {
12103                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12104                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12105                                 if (!rsurface.texture->currentlayers->depthmask)
12106                                         GL_Color(c, 0, 0, 1.0f);
12107                                 else if (ent == r_refdef.scene.worldentity)
12108                                         GL_Color(c, c, c, 1.0f);
12109                                 else
12110                                         GL_Color(0, c, 0, 1.0f);
12111                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12112                                 RSurf_DrawBatch();
12113                         }
12114                 }
12115                 rsurface.texture = NULL;
12116         }
12117
12118         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12119
12120 //      R_Mesh_ResetTextureState();
12121         R_SetupShader_Generic_NoTexture(false, false);
12122         GL_DepthRange(0, 1);
12123         GL_DepthTest(!r_showdisabledepthtest.integer);
12124         GL_DepthMask(false);
12125         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12126
12127         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12128         {
12129                 int triangleindex;
12130                 int bihleafindex;
12131                 qboolean cullbox = false;
12132                 const q3mbrush_t *brush;
12133                 const bih_t *bih = &model->collision_bih;
12134                 const bih_leaf_t *bihleaf;
12135                 float vertex3f[3][3];
12136                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12137                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12138                 {
12139                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12140                                 continue;
12141                         switch (bihleaf->type)
12142                         {
12143                         case BIH_BRUSH:
12144                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12145                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12146                                 {
12147                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12148                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12149                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12150                                 }
12151                                 break;
12152                         case BIH_COLLISIONTRIANGLE:
12153                                 triangleindex = bihleaf->itemindex;
12154                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12155                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12156                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12157                                 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);
12158                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12159                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12160                                 break;
12161                         case BIH_RENDERTRIANGLE:
12162                                 triangleindex = bihleaf->itemindex;
12163                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12164                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12165                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12166                                 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);
12167                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12168                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12169                                 break;
12170                         }
12171                 }
12172         }
12173
12174         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12175
12176 #ifndef USE_GLES2
12177         if (r_showtris.integer && qglPolygonMode)
12178         {
12179                 if (r_showdisabledepthtest.integer)
12180                 {
12181                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12182                         GL_DepthMask(false);
12183                 }
12184                 else
12185                 {
12186                         GL_BlendFunc(GL_ONE, GL_ZERO);
12187                         GL_DepthMask(true);
12188                 }
12189                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12190                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12191                 {
12192                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12193                                 continue;
12194                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12195                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12196                         {
12197                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12198                                 if (!rsurface.texture->currentlayers->depthmask)
12199                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12200                                 else if (ent == r_refdef.scene.worldentity)
12201                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12202                                 else
12203                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12204                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12205                                 RSurf_DrawBatch();
12206                         }
12207                 }
12208                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12209                 rsurface.texture = NULL;
12210         }
12211
12212         if (r_shownormals.value != 0 && qglBegin)
12213         {
12214                 int l, k;
12215                 vec3_t v;
12216                 if (r_showdisabledepthtest.integer)
12217                 {
12218                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12219                         GL_DepthMask(false);
12220                 }
12221                 else
12222                 {
12223                         GL_BlendFunc(GL_ONE, GL_ZERO);
12224                         GL_DepthMask(true);
12225                 }
12226                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12227                 {
12228                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12229                                 continue;
12230                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12231                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12232                         {
12233                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12234                                 qglBegin(GL_LINES);
12235                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12236                                 {
12237                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12238                                         {
12239                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12240                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12241                                                 qglVertex3f(v[0], v[1], v[2]);
12242                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12243                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12244                                                 qglVertex3f(v[0], v[1], v[2]);
12245                                         }
12246                                 }
12247                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12248                                 {
12249                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12250                                         {
12251                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12252                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12253                                                 qglVertex3f(v[0], v[1], v[2]);
12254                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12255                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12256                                                 qglVertex3f(v[0], v[1], v[2]);
12257                                         }
12258                                 }
12259                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12260                                 {
12261                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12262                                         {
12263                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12264                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12265                                                 qglVertex3f(v[0], v[1], v[2]);
12266                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12267                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12268                                                 qglVertex3f(v[0], v[1], v[2]);
12269                                         }
12270                                 }
12271                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12272                                 {
12273                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12274                                         {
12275                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12276                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12277                                                 qglVertex3f(v[0], v[1], v[2]);
12278                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12279                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12280                                                 qglVertex3f(v[0], v[1], v[2]);
12281                                         }
12282                                 }
12283                                 qglEnd();
12284                                 CHECKGLERROR
12285                         }
12286                 }
12287                 rsurface.texture = NULL;
12288         }
12289 #endif
12290 }
12291
12292 int r_maxsurfacelist = 0;
12293 const msurface_t **r_surfacelist = NULL;
12294 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12295 {
12296         int i, j, endj, flagsmask;
12297         dp_model_t *model = ent->model;
12298         msurface_t *surfaces;
12299         unsigned char *update;
12300         int numsurfacelist = 0;
12301         if (model == NULL)
12302                 return;
12303
12304         if (r_maxsurfacelist < model->num_surfaces)
12305         {
12306                 r_maxsurfacelist = model->num_surfaces;
12307                 if (r_surfacelist)
12308                         Mem_Free((msurface_t **)r_surfacelist);
12309                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12310         }
12311
12312         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12313                 RSurf_ActiveModelEntity(ent, false, false, false);
12314         else if (prepass)
12315                 RSurf_ActiveModelEntity(ent, true, true, true);
12316         else if (depthonly)
12317         {
12318                 switch (vid.renderpath)
12319                 {
12320                 case RENDERPATH_GL20:
12321                 case RENDERPATH_D3D9:
12322                 case RENDERPATH_D3D10:
12323                 case RENDERPATH_D3D11:
12324                 case RENDERPATH_SOFT:
12325                 case RENDERPATH_GLES2:
12326                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12327                         break;
12328                 case RENDERPATH_GL11:
12329                 case RENDERPATH_GL13:
12330                 case RENDERPATH_GLES1:
12331                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12332                         break;
12333                 }
12334         }
12335         else
12336         {
12337                 switch (vid.renderpath)
12338                 {
12339                 case RENDERPATH_GL20:
12340                 case RENDERPATH_D3D9:
12341                 case RENDERPATH_D3D10:
12342                 case RENDERPATH_D3D11:
12343                 case RENDERPATH_SOFT:
12344                 case RENDERPATH_GLES2:
12345                         RSurf_ActiveModelEntity(ent, true, true, false);
12346                         break;
12347                 case RENDERPATH_GL11:
12348                 case RENDERPATH_GL13:
12349                 case RENDERPATH_GLES1:
12350                         RSurf_ActiveModelEntity(ent, true, false, false);
12351                         break;
12352                 }
12353         }
12354
12355         surfaces = model->data_surfaces;
12356         update = model->brushq1.lightmapupdateflags;
12357
12358         // update light styles
12359         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12360         {
12361                 model_brush_lightstyleinfo_t *style;
12362                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12363                 {
12364                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12365                         {
12366                                 int *list = style->surfacelist;
12367                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12368                                 for (j = 0;j < style->numsurfaces;j++)
12369                                         update[list[j]] = true;
12370                         }
12371                 }
12372         }
12373
12374         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12375
12376         if (debug)
12377         {
12378                 R_DrawDebugModel();
12379                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12380                 return;
12381         }
12382
12383         rsurface.lightmaptexture = NULL;
12384         rsurface.deluxemaptexture = NULL;
12385         rsurface.uselightmaptexture = false;
12386         rsurface.texture = NULL;
12387         rsurface.rtlight = NULL;
12388         numsurfacelist = 0;
12389         // add visible surfaces to draw list
12390         if (ent == r_refdef.scene.worldentity)
12391         {
12392                 // for the world entity, check surfacevisible
12393                 for (i = 0;i < model->nummodelsurfaces;i++)
12394                 {
12395                         j = model->sortedmodelsurfaces[i];
12396                         if (r_refdef.viewcache.world_surfacevisible[j])
12397                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12398                 }
12399         }
12400         else
12401         {
12402                 // add all surfaces
12403                 for (i = 0; i < model->nummodelsurfaces; i++)
12404                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12405         }
12406         // don't do anything if there were no surfaces
12407         if (!numsurfacelist)
12408         {
12409                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12410                 return;
12411         }
12412         // update lightmaps if needed
12413         if (update)
12414         {
12415                 int updated = 0;
12416                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12417                 {
12418                         if (update[j])
12419                         {
12420                                 updated++;
12421                                 R_BuildLightMap(ent, surfaces + j);
12422                         }
12423                 }
12424         }
12425
12426         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12427
12428         // add to stats if desired
12429         if (r_speeds.integer && !skysurfaces && !depthonly)
12430         {
12431                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12432                 for (j = 0;j < numsurfacelist;j++)
12433                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12434         }
12435
12436         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12437 }
12438
12439 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12440 {
12441         int q;
12442         static texture_t texture;
12443         static msurface_t surface;
12444         const msurface_t *surfacelist = &surface;
12445
12446         // fake enough texture and surface state to render this geometry
12447
12448         texture.update_lastrenderframe = -1; // regenerate this texture
12449         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12450         texture.basealpha = 1.0f;
12451         texture.currentskinframe = skinframe;
12452         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12453         texture.offsetmapping = OFFSETMAPPING_OFF;
12454         texture.offsetscale = 1;
12455         texture.specularscalemod = 1;
12456         texture.specularpowermod = 1;
12457         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12458
12459         R_DrawCustomSurface_Texture(&texture, texmatrix, materialflags, firstvertex, numvertices, firsttriangle, numtriangles, writedepth, prepass);
12460 }
12461
12462 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)
12463 {
12464         static msurface_t surface;
12465         const msurface_t *surfacelist = &surface;
12466
12467         // fake enough texture and surface state to render this geometry
12468         surface.texture = texture;
12469         surface.num_triangles = numtriangles;
12470         surface.num_firsttriangle = firsttriangle;
12471         surface.num_vertices = numvertices;
12472         surface.num_firstvertex = firstvertex;
12473
12474         // now render it
12475         rsurface.texture = R_GetCurrentTexture(surface.texture);
12476         rsurface.lightmaptexture = NULL;
12477         rsurface.deluxemaptexture = NULL;
12478         rsurface.uselightmaptexture = false;
12479         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12480 }